1 /******************************************************************************
   2  *
   3  * Module Name: aslresource - Resource template/descriptor utilities
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 
  45 #include "aslcompiler.h"
  46 #include "aslcompiler.y.h"
  47 #include "amlcode.h"
  48 
  49 
  50 #define _COMPONENT          ACPI_COMPILER
  51         ACPI_MODULE_NAME    ("aslresource")
  52 
  53 
  54 /*******************************************************************************
  55  *
  56  * FUNCTION:    RsSmallAddressCheck
  57  *
  58  * PARAMETERS:  Minimum             - Address Min value
  59  *              Maximum             - Address Max value
  60  *              Length              - Address range value
  61  *              Alignment           - Address alignment value
  62  *              MinOp               - Original Op for Address Min
  63  *              MaxOp               - Original Op for Address Max
  64  *              LengthOp            - Original Op for address range
  65  *              AlignOp             - Original Op for address alignment. If
  66  *                                    NULL, means "zero value for alignment is
  67  *                                    OK, and means 64K alignment" (for
  68  *                                    Memory24 descriptor)
  69  *              Op                  - Parent Op for entire construct
  70  *
  71  * RETURN:      None. Adds error messages to error log if necessary
  72  *
  73  * DESCRIPTION: Perform common value checks for "small" address descriptors.
  74  *              Currently:
  75  *                  Io, Memory24, Memory32
  76  *
  77  ******************************************************************************/
  78 
  79 void
  80 RsSmallAddressCheck (
  81     UINT8                   Type,
  82     UINT32                  Minimum,
  83     UINT32                  Maximum,
  84     UINT32                  Length,
  85     UINT32                  Alignment,
  86     ACPI_PARSE_OBJECT       *MinOp,
  87     ACPI_PARSE_OBJECT       *MaxOp,
  88     ACPI_PARSE_OBJECT       *LengthOp,
  89     ACPI_PARSE_OBJECT       *AlignOp,
  90     ACPI_PARSE_OBJECT       *Op)
  91 {
  92 
  93     if (Gbl_NoResourceChecking)
  94     {
  95         return;
  96     }
  97 
  98     /*
  99      * Check for a so-called "null descriptor". These are descriptors that are
 100      * created with most fields set to zero. The intent is that the descriptor
 101      * will be updated/completed at runtime via a BufferField.
 102      *
 103      * If the descriptor does NOT have a resource tag, it cannot be referenced
 104      * by a BufferField and we will flag this as an error. Conversely, if
 105      * the descriptor has a resource tag, we will assume that a BufferField
 106      * will be used to dynamically update it, so no error.
 107      *
 108      * A possible enhancement to this check would be to verify that in fact
 109      * a BufferField is created using the resource tag, and perhaps even
 110      * verify that a Store is performed to the BufferField.
 111      *
 112      * Note: for these descriptors, Alignment is allowed to be zero
 113      */
 114     if (!Minimum && !Maximum && !Length)
 115     {
 116         if (!Op->Asl.ExternalName)
 117         {
 118             /* No resource tag. Descriptor is fixed and is also illegal */
 119 
 120             AslError (ASL_ERROR, ASL_MSG_NULL_DESCRIPTOR, Op, NULL);
 121         }
 122 
 123         return;
 124     }
 125 
 126     /* Special case for Memory24, values are compressed */
 127 
 128     if (Type == ACPI_RESOURCE_NAME_MEMORY24)
 129     {
 130         if (!Alignment) /* Alignment==0 means 64K - no invalid alignment */
 131         {
 132             Alignment = ACPI_UINT16_MAX + 1;
 133         }
 134 
 135         Minimum <<= 8;
 136         Maximum <<= 8;
 137         Length *= 256;
 138     }
 139 
 140     /* IO descriptor has different definition of min/max, don't check */
 141 
 142     if (Type != ACPI_RESOURCE_NAME_IO)
 143     {
 144         /* Basic checks on Min/Max/Length */
 145 
 146         if (Minimum > Maximum)
 147         {
 148             AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
 149         }
 150         else if (Length > (Maximum - Minimum + 1))
 151         {
 152             AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
 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 (Gbl_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         InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
 400     }
 401 
 402     return (0);
 403 }
 404 
 405 
 406 /*******************************************************************************
 407  *
 408  * FUNCTION:    RsAllocateResourceNode
 409  *
 410  * PARAMETERS:  Size        - Size of node in bytes
 411  *
 412  * RETURN:      The allocated node - aborts on allocation failure
 413  *
 414  * DESCRIPTION: Allocate a resource description node and the resource
 415  *              descriptor itself (the nodes are used to link descriptors).
 416  *
 417  ******************************************************************************/
 418 
 419 ASL_RESOURCE_NODE *
 420 RsAllocateResourceNode (
 421     UINT32                  Size)
 422 {
 423     ASL_RESOURCE_NODE       *Rnode;
 424 
 425 
 426     /* Allocate the node */
 427 
 428     Rnode = UtLocalCalloc (sizeof (ASL_RESOURCE_NODE));
 429 
 430     /* Allocate the resource descriptor itself */
 431 
 432     Rnode->Buffer = UtLocalCalloc (Size);
 433     Rnode->BufferLength = Size;
 434 
 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 |= NODE_IS_RESOURCE_FIELD;
 469 
 470 
 471     Op->Asl.Value.Tag.BitOffset = (ByteOffset * 8) + BitOffset;
 472     Op->Asl.Value.Tag.BitLength = BitLength;
 473 }
 474 
 475 
 476 /*******************************************************************************
 477  *
 478  * FUNCTION:    RsSetFlagBits
 479  *
 480  * PARAMETERS:  *Flags          - Pointer to the flag byte
 481  *              Op              - Flag initialization node
 482  *              Position        - Bit position within the flag byte
 483  *              Default         - Used if the node is DEFAULT.
 484  *
 485  * RETURN:      Sets bits within the *Flags output byte.
 486  *
 487  * DESCRIPTION: Set a bit in a cumulative flags word from an initialization
 488  *              node. Will use a default value if the node is DEFAULT, meaning
 489  *              that no value was specified in the ASL. Used to merge multiple
 490  *              keywords into a single flags byte.
 491  *
 492  ******************************************************************************/
 493 
 494 void
 495 RsSetFlagBits (
 496     UINT8                   *Flags,
 497     ACPI_PARSE_OBJECT       *Op,
 498     UINT8                   Position,
 499     UINT8                   DefaultBit)
 500 {
 501 
 502     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
 503     {
 504         /* Use the default bit */
 505 
 506         *Flags |= (DefaultBit << Position);
 507     }
 508     else
 509     {
 510         /* Use the bit specified in the initialization node */
 511 
 512         *Flags |= (((UINT8) Op->Asl.Value.Integer) << Position);
 513     }
 514 }
 515 
 516 
 517 void
 518 RsSetFlagBits16 (
 519     UINT16                  *Flags,
 520     ACPI_PARSE_OBJECT       *Op,
 521     UINT8                   Position,
 522     UINT8                   DefaultBit)
 523 {
 524 
 525     if (Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
 526     {
 527         /* Use the default bit */
 528 
 529         *Flags |= (DefaultBit << Position);
 530     }
 531     else
 532     {
 533         /* Use the bit specified in the initialization node */
 534 
 535         *Flags |= (((UINT16) Op->Asl.Value.Integer) << Position);
 536     }
 537 }
 538 
 539 
 540 /*******************************************************************************
 541  *
 542  * FUNCTION:    RsCompleteNodeAndGetNext
 543  *
 544  * PARAMETERS:  Op            - Resource node to be completed
 545  *
 546  * RETURN:      The next peer to the input node.
 547  *
 548  * DESCRIPTION: Mark the current node completed and return the next peer.
 549  *              The node ParseOpcode is set to DEFAULT_ARG, meaning that
 550  *              this node is to be ignored from now on.
 551  *
 552  ******************************************************************************/
 553 
 554 ACPI_PARSE_OBJECT *
 555 RsCompleteNodeAndGetNext (
 556     ACPI_PARSE_OBJECT       *Op)
 557 {
 558 
 559     /* Mark this node unused */
 560 
 561     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
 562 
 563     /* Move on to the next peer node in the initializer list */
 564 
 565     return (ASL_GET_PEER_NODE (Op));
 566 }
 567 
 568 
 569 /*******************************************************************************
 570  *
 571  * FUNCTION:    RsCheckListForDuplicates
 572  *
 573  * PARAMETERS:  Op                  - First op in the initializer list
 574  *
 575  * RETURN:      None
 576  *
 577  * DESCRIPTION: Check an initializer list for duplicate values. Emits an error
 578  *              if any duplicates are found.
 579  *
 580  ******************************************************************************/
 581 
 582 void
 583 RsCheckListForDuplicates (
 584     ACPI_PARSE_OBJECT       *Op)
 585 {
 586     ACPI_PARSE_OBJECT       *NextValueOp = Op;
 587     ACPI_PARSE_OBJECT       *NextOp;
 588     UINT32                  Value;
 589 
 590 
 591     if (!Op)
 592     {
 593         return;
 594     }
 595 
 596     /* Search list once for each value in the list */
 597 
 598     while (NextValueOp)
 599     {
 600         Value = (UINT32) NextValueOp->Asl.Value.Integer;
 601 
 602         /* Compare this value to all remaining values in the list */
 603 
 604         NextOp = ASL_GET_PEER_NODE (NextValueOp);
 605         while (NextOp)
 606         {
 607             if (NextOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
 608             {
 609                 /* Compare values */
 610 
 611                 if (Value == (UINT32) NextOp->Asl.Value.Integer)
 612                 {
 613                     /* Emit error only once per duplicate node */
 614 
 615                     if (!(NextOp->Asl.CompileFlags & NODE_IS_DUPLICATE))
 616                     {
 617                         NextOp->Asl.CompileFlags |= NODE_IS_DUPLICATE;
 618                         AslError (ASL_ERROR, ASL_MSG_DUPLICATE_ITEM,
 619                             NextOp, NULL);
 620                     }
 621                 }
 622             }
 623 
 624             NextOp = ASL_GET_PEER_NODE (NextOp);
 625         }
 626 
 627         NextValueOp = ASL_GET_PEER_NODE (NextValueOp);
 628     }
 629 }
 630 
 631 
 632 /*******************************************************************************
 633  *
 634  * FUNCTION:    RsDoOneResourceDescriptor
 635  *
 636  * PARAMETERS:  DescriptorTypeOp    - Parent parse node of the descriptor
 637  *              CurrentByteOffset   - Offset in the resource descriptor
 638  *                                    buffer.
 639  *
 640  * RETURN:      A valid resource node for the descriptor
 641  *
 642  * DESCRIPTION: Dispatches the processing of one resource descriptor
 643  *
 644  ******************************************************************************/
 645 
 646 ASL_RESOURCE_NODE *
 647 RsDoOneResourceDescriptor (
 648     ACPI_PARSE_OBJECT       *DescriptorTypeOp,
 649     UINT32                  CurrentByteOffset,
 650     UINT8                   *State)
 651 {
 652     ASL_RESOURCE_NODE       *Rnode = NULL;
 653 
 654 
 655     /* Construct the resource */
 656 
 657     switch (DescriptorTypeOp->Asl.ParseOpcode)
 658     {
 659     case PARSEOP_DMA:
 660 
 661         Rnode = RsDoDmaDescriptor (DescriptorTypeOp,
 662                     CurrentByteOffset);
 663         break;
 664 
 665     case PARSEOP_FIXEDDMA:
 666 
 667         Rnode = RsDoFixedDmaDescriptor (DescriptorTypeOp,
 668                     CurrentByteOffset);
 669         break;
 670 
 671     case PARSEOP_DWORDIO:
 672 
 673         Rnode = RsDoDwordIoDescriptor (DescriptorTypeOp,
 674                     CurrentByteOffset);
 675         break;
 676 
 677     case PARSEOP_DWORDMEMORY:
 678 
 679         Rnode = RsDoDwordMemoryDescriptor (DescriptorTypeOp,
 680                     CurrentByteOffset);
 681         break;
 682 
 683     case PARSEOP_DWORDSPACE:
 684 
 685         Rnode = RsDoDwordSpaceDescriptor (DescriptorTypeOp,
 686                     CurrentByteOffset);
 687         break;
 688 
 689     case PARSEOP_ENDDEPENDENTFN:
 690 
 691         switch (*State)
 692         {
 693         case ACPI_RSTATE_NORMAL:
 694 
 695             AslError (ASL_ERROR, ASL_MSG_MISSING_STARTDEPENDENT,
 696                 DescriptorTypeOp, NULL);
 697             break;
 698 
 699         case ACPI_RSTATE_START_DEPENDENT:
 700 
 701             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
 702                 DescriptorTypeOp, NULL);
 703             break;
 704 
 705         case ACPI_RSTATE_DEPENDENT_LIST:
 706         default:
 707 
 708             break;
 709         }
 710 
 711         *State = ACPI_RSTATE_NORMAL;
 712         Rnode = RsDoEndDependentDescriptor (DescriptorTypeOp,
 713                     CurrentByteOffset);
 714         break;
 715 
 716     case PARSEOP_ENDTAG:
 717 
 718         Rnode = RsDoEndTagDescriptor (DescriptorTypeOp,
 719                     CurrentByteOffset);
 720         break;
 721 
 722     case PARSEOP_EXTENDEDIO:
 723 
 724         Rnode = RsDoExtendedIoDescriptor (DescriptorTypeOp,
 725                     CurrentByteOffset);
 726         break;
 727 
 728     case PARSEOP_EXTENDEDMEMORY:
 729 
 730         Rnode = RsDoExtendedMemoryDescriptor (DescriptorTypeOp,
 731                     CurrentByteOffset);
 732         break;
 733 
 734     case PARSEOP_EXTENDEDSPACE:
 735 
 736         Rnode = RsDoExtendedSpaceDescriptor (DescriptorTypeOp,
 737                     CurrentByteOffset);
 738         break;
 739 
 740     case PARSEOP_FIXEDIO:
 741 
 742         Rnode = RsDoFixedIoDescriptor (DescriptorTypeOp,
 743                     CurrentByteOffset);
 744         break;
 745 
 746     case PARSEOP_INTERRUPT:
 747 
 748         Rnode = RsDoInterruptDescriptor (DescriptorTypeOp,
 749                     CurrentByteOffset);
 750         break;
 751 
 752     case PARSEOP_IO:
 753 
 754         Rnode = RsDoIoDescriptor (DescriptorTypeOp,
 755                     CurrentByteOffset);
 756         break;
 757 
 758     case PARSEOP_IRQ:
 759 
 760         Rnode = RsDoIrqDescriptor (DescriptorTypeOp,
 761                     CurrentByteOffset);
 762         break;
 763 
 764     case PARSEOP_IRQNOFLAGS:
 765 
 766         Rnode = RsDoIrqNoFlagsDescriptor (DescriptorTypeOp,
 767                     CurrentByteOffset);
 768         break;
 769 
 770     case PARSEOP_MEMORY24:
 771 
 772         Rnode = RsDoMemory24Descriptor (DescriptorTypeOp,
 773                     CurrentByteOffset);
 774         break;
 775 
 776     case PARSEOP_MEMORY32:
 777 
 778         Rnode = RsDoMemory32Descriptor (DescriptorTypeOp,
 779                     CurrentByteOffset);
 780         break;
 781 
 782     case PARSEOP_MEMORY32FIXED:
 783 
 784         Rnode = RsDoMemory32FixedDescriptor (DescriptorTypeOp,
 785                     CurrentByteOffset);
 786         break;
 787 
 788     case PARSEOP_QWORDIO:
 789 
 790         Rnode = RsDoQwordIoDescriptor (DescriptorTypeOp,
 791                     CurrentByteOffset);
 792         break;
 793 
 794     case PARSEOP_QWORDMEMORY:
 795 
 796         Rnode = RsDoQwordMemoryDescriptor (DescriptorTypeOp,
 797                     CurrentByteOffset);
 798         break;
 799 
 800     case PARSEOP_QWORDSPACE:
 801 
 802         Rnode = RsDoQwordSpaceDescriptor (DescriptorTypeOp,
 803                     CurrentByteOffset);
 804         break;
 805 
 806     case PARSEOP_REGISTER:
 807 
 808         Rnode = RsDoGeneralRegisterDescriptor (DescriptorTypeOp,
 809                     CurrentByteOffset);
 810         break;
 811 
 812     case PARSEOP_STARTDEPENDENTFN:
 813 
 814         switch (*State)
 815         {
 816         case ACPI_RSTATE_START_DEPENDENT:
 817 
 818             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
 819                 DescriptorTypeOp, NULL);
 820             break;
 821 
 822         case ACPI_RSTATE_NORMAL:
 823         case ACPI_RSTATE_DEPENDENT_LIST:
 824         default:
 825 
 826             break;
 827         }
 828 
 829         *State = ACPI_RSTATE_START_DEPENDENT;
 830         Rnode = RsDoStartDependentDescriptor (DescriptorTypeOp,
 831                     CurrentByteOffset);
 832         *State = ACPI_RSTATE_DEPENDENT_LIST;
 833         break;
 834 
 835     case PARSEOP_STARTDEPENDENTFN_NOPRI:
 836 
 837         switch (*State)
 838         {
 839         case ACPI_RSTATE_START_DEPENDENT:
 840 
 841             AslError (ASL_ERROR, ASL_MSG_DEPENDENT_NESTING,
 842                 DescriptorTypeOp, NULL);
 843             break;
 844 
 845         case ACPI_RSTATE_NORMAL:
 846         case ACPI_RSTATE_DEPENDENT_LIST:
 847         default:
 848 
 849             break;
 850         }
 851 
 852         *State = ACPI_RSTATE_START_DEPENDENT;
 853         Rnode = RsDoStartDependentNoPriDescriptor (DescriptorTypeOp,
 854                     CurrentByteOffset);
 855         *State = ACPI_RSTATE_DEPENDENT_LIST;
 856         break;
 857 
 858     case PARSEOP_VENDORLONG:
 859 
 860         Rnode = RsDoVendorLargeDescriptor (DescriptorTypeOp,
 861                     CurrentByteOffset);
 862         break;
 863 
 864     case PARSEOP_VENDORSHORT:
 865 
 866         Rnode = RsDoVendorSmallDescriptor (DescriptorTypeOp,
 867                     CurrentByteOffset);
 868         break;
 869 
 870     case PARSEOP_WORDBUSNUMBER:
 871 
 872         Rnode = RsDoWordBusNumberDescriptor (DescriptorTypeOp,
 873                     CurrentByteOffset);
 874         break;
 875 
 876     case PARSEOP_WORDIO:
 877 
 878         Rnode = RsDoWordIoDescriptor (DescriptorTypeOp,
 879                     CurrentByteOffset);
 880         break;
 881 
 882     case PARSEOP_WORDSPACE:
 883 
 884         Rnode = RsDoWordSpaceDescriptor (DescriptorTypeOp,
 885                     CurrentByteOffset);
 886         break;
 887 
 888     case PARSEOP_GPIO_INT:
 889 
 890         Rnode = RsDoGpioIntDescriptor (DescriptorTypeOp,
 891                     CurrentByteOffset);
 892         break;
 893 
 894     case PARSEOP_GPIO_IO:
 895 
 896         Rnode = RsDoGpioIoDescriptor (DescriptorTypeOp,
 897                     CurrentByteOffset);
 898         break;
 899 
 900     case PARSEOP_I2C_SERIALBUS:
 901 
 902         Rnode = RsDoI2cSerialBusDescriptor (DescriptorTypeOp,
 903                     CurrentByteOffset);
 904         break;
 905 
 906     case PARSEOP_SPI_SERIALBUS:
 907 
 908         Rnode = RsDoSpiSerialBusDescriptor (DescriptorTypeOp,
 909                     CurrentByteOffset);
 910         break;
 911 
 912     case PARSEOP_UART_SERIALBUS:
 913 
 914         Rnode = RsDoUartSerialBusDescriptor (DescriptorTypeOp,
 915                     CurrentByteOffset);
 916         break;
 917 
 918     case PARSEOP_DEFAULT_ARG:
 919 
 920         /* Just ignore any of these, they are used as fillers/placeholders */
 921         break;
 922 
 923     default:
 924 
 925         printf ("Unknown resource descriptor type [%s]\n",
 926                     DescriptorTypeOp->Asl.ParseOpName);
 927         break;
 928     }
 929 
 930     /*
 931      * Mark original node as unused, but head of a resource descriptor.
 932      * This allows the resource to be installed in the namespace so that
 933      * references to the descriptor can be resolved.
 934      */
 935     DescriptorTypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
 936     DescriptorTypeOp->Asl.CompileFlags = NODE_IS_RESOURCE_DESC;
 937     DescriptorTypeOp->Asl.Value.Integer = CurrentByteOffset;
 938 
 939     if (Rnode)
 940     {
 941         DescriptorTypeOp->Asl.FinalAmlLength = Rnode->BufferLength;
 942         DescriptorTypeOp->Asl.Extra = ((AML_RESOURCE *) Rnode->Buffer)->DescriptorType;
 943     }
 944 
 945     return (Rnode);
 946 }
 947 
 948 
 949 /*******************************************************************************
 950  *
 951  * FUNCTION:    RsLinkDescriptorChain
 952  *
 953  * PARAMETERS:  PreviousRnode       - Pointer to the node that will be previous
 954  *                                    to the linked node,  At exit, set to the
 955  *                                    last node in the new chain.
 956  *              Rnode               - Resource node to link into the list
 957  *
 958  * RETURN:      Cumulative buffer byte offset of the new segment of chain
 959  *
 960  * DESCRIPTION: Link a descriptor chain at the end of an existing chain.
 961  *
 962  ******************************************************************************/
 963 
 964 UINT32
 965 RsLinkDescriptorChain (
 966     ASL_RESOURCE_NODE       **PreviousRnode,
 967     ASL_RESOURCE_NODE       *Rnode)
 968 {
 969     ASL_RESOURCE_NODE       *LastRnode;
 970     UINT32                  CurrentByteOffset;
 971 
 972 
 973     /* Anything to do? */
 974 
 975     if (!Rnode)
 976     {
 977         return (0);
 978     }
 979 
 980     /* Point the previous node to the new node */
 981 
 982     (*PreviousRnode)->Next = Rnode;
 983     CurrentByteOffset = Rnode->BufferLength;
 984 
 985     /* Walk to the end of the chain headed by Rnode */
 986 
 987     LastRnode = Rnode;
 988     while (LastRnode->Next)
 989     {
 990         LastRnode = LastRnode->Next;
 991         CurrentByteOffset += LastRnode->BufferLength;
 992     }
 993 
 994     /* Previous node becomes the last node in the chain */
 995 
 996     *PreviousRnode = LastRnode;
 997     return (CurrentByteOffset);
 998 }
 999 
1000 
1001 /*******************************************************************************
1002  *
1003  * FUNCTION:    RsDoResourceTemplate
1004  *
1005  * PARAMETERS:  Op        - Parent of a resource template list
1006  *
1007  * RETURN:      None. Sets input node to point to a list of AML code
1008  *
1009  * DESCRIPTION: Merge a list of resource descriptors into a single AML buffer,
1010  *              in preparation for output to the AML output file.
1011  *
1012  ******************************************************************************/
1013 
1014 void
1015 RsDoResourceTemplate (
1016     ACPI_PARSE_OBJECT       *Op)
1017 {
1018     ACPI_PARSE_OBJECT       *BufferLengthOp;
1019     ACPI_PARSE_OBJECT       *BufferOp;
1020     ACPI_PARSE_OBJECT       *DescriptorTypeOp;
1021     ACPI_PARSE_OBJECT       *LastOp = NULL;
1022     UINT32                  CurrentByteOffset = 0;
1023     ASL_RESOURCE_NODE       HeadRnode;
1024     ASL_RESOURCE_NODE       *PreviousRnode;
1025     ASL_RESOURCE_NODE       *Rnode;
1026     UINT8                   State;
1027 
1028 
1029     /* Mark parent as containing a resource template */
1030 
1031     if (Op->Asl.Parent)
1032     {
1033         Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1034     }
1035 
1036     /* ResourceTemplate Opcode is first (Op) */
1037     /* Buffer Length node is first child */
1038 
1039     BufferLengthOp = ASL_GET_CHILD_NODE (Op);
1040 
1041     /* Buffer Op is first peer */
1042 
1043     BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);
1044 
1045     /* First Descriptor type is next */
1046 
1047     DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);
1048 
1049     /*
1050      * Process all resource descriptors in the list
1051      * Note: It is assumed that the EndTag node has been automatically
1052      * inserted at the end of the template by the parser.
1053      */
1054     State = ACPI_RSTATE_NORMAL;
1055     PreviousRnode = &HeadRnode;
1056     while (DescriptorTypeOp)
1057     {
1058         DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
1059         Rnode = RsDoOneResourceDescriptor (DescriptorTypeOp, CurrentByteOffset,
1060                     &State);
1061 
1062         /*
1063          * Update current byte offset to indicate the number of bytes from the
1064          * start of the buffer. Buffer can include multiple descriptors, we
1065          * must keep track of the offset of not only each descriptor, but each
1066          * element (field) within each descriptor as well.
1067          */
1068         CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);
1069 
1070         /* Get the next descriptor in the list */
1071 
1072         LastOp = DescriptorTypeOp;
1073         DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
1074     }
1075 
1076     if (State == ACPI_RSTATE_DEPENDENT_LIST)
1077     {
1078         if (LastOp)
1079         {
1080             LastOp = LastOp->Asl.Parent;
1081         }
1082         AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
1083     }
1084 
1085     /*
1086      * Transform the nodes into the following
1087      *
1088      * Op           -> AML_BUFFER_OP
1089      * First Child  -> BufferLength
1090      * Second Child -> Descriptor Buffer (raw byte data)
1091      */
1092     Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
1093     Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
1094     Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
1095     UtSetParseOpName (Op);
1096 
1097     BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
1098     BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
1099     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
1100     UtSetParseOpName (BufferLengthOp);
1101 
1102     BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
1103     BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
1104     BufferOp->Asl.AmlOpcodeLength     = 0;
1105     BufferOp->Asl.AmlLength           = CurrentByteOffset;
1106     BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
1107     BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
1108     UtSetParseOpName (BufferOp);
1109 
1110     return;
1111 }