1 /*******************************************************************************
   2  *
   3  * Module Name: utresrc - Resource managment utilities
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, 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 #define __UTRESRC_C__
  46 
  47 #include "acpi.h"
  48 #include "accommon.h"
  49 #include "amlresrc.h"
  50 
  51 
  52 #define _COMPONENT          ACPI_UTILITIES
  53         ACPI_MODULE_NAME    ("utresrc")
  54 
  55 
  56 #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
  57 
  58 /*
  59  * Strings used to decode resource descriptors.
  60  * Used by both the disasssembler and the debugger resource dump routines
  61  */
  62 const char                      *AcpiGbl_BmDecode[] =
  63 {
  64     "NotBusMaster",
  65     "BusMaster"
  66 };
  67 
  68 const char                      *AcpiGbl_ConfigDecode[] =
  69 {
  70     "0 - Good Configuration",
  71     "1 - Acceptable Configuration",
  72     "2 - Suboptimal Configuration",
  73     "3 - ***Invalid Configuration***",
  74 };
  75 
  76 const char                      *AcpiGbl_ConsumeDecode[] =
  77 {
  78     "ResourceProducer",
  79     "ResourceConsumer"
  80 };
  81 
  82 const char                      *AcpiGbl_DecDecode[] =
  83 {
  84     "PosDecode",
  85     "SubDecode"
  86 };
  87 
  88 const char                      *AcpiGbl_HeDecode[] =
  89 {
  90     "Level",
  91     "Edge"
  92 };
  93 
  94 const char                      *AcpiGbl_IoDecode[] =
  95 {
  96     "Decode10",
  97     "Decode16"
  98 };
  99 
 100 const char                      *AcpiGbl_LlDecode[] =
 101 {
 102     "ActiveHigh",
 103     "ActiveLow"
 104 };
 105 
 106 const char                      *AcpiGbl_MaxDecode[] =
 107 {
 108     "MaxNotFixed",
 109     "MaxFixed"
 110 };
 111 
 112 const char                      *AcpiGbl_MemDecode[] =
 113 {
 114     "NonCacheable",
 115     "Cacheable",
 116     "WriteCombining",
 117     "Prefetchable"
 118 };
 119 
 120 const char                      *AcpiGbl_MinDecode[] =
 121 {
 122     "MinNotFixed",
 123     "MinFixed"
 124 };
 125 
 126 const char                      *AcpiGbl_MtpDecode[] =
 127 {
 128     "AddressRangeMemory",
 129     "AddressRangeReserved",
 130     "AddressRangeACPI",
 131     "AddressRangeNVS"
 132 };
 133 
 134 const char                      *AcpiGbl_RngDecode[] =
 135 {
 136     "InvalidRanges",
 137     "NonISAOnlyRanges",
 138     "ISAOnlyRanges",
 139     "EntireRange"
 140 };
 141 
 142 const char                      *AcpiGbl_RwDecode[] =
 143 {
 144     "ReadOnly",
 145     "ReadWrite"
 146 };
 147 
 148 const char                      *AcpiGbl_ShrDecode[] =
 149 {
 150     "Exclusive",
 151     "Shared"
 152 };
 153 
 154 const char                      *AcpiGbl_SizDecode[] =
 155 {
 156     "Transfer8",
 157     "Transfer8_16",
 158     "Transfer16",
 159     "InvalidSize"
 160 };
 161 
 162 const char                      *AcpiGbl_TrsDecode[] =
 163 {
 164     "DenseTranslation",
 165     "SparseTranslation"
 166 };
 167 
 168 const char                      *AcpiGbl_TtpDecode[] =
 169 {
 170     "TypeStatic",
 171     "TypeTranslation"
 172 };
 173 
 174 const char                      *AcpiGbl_TypDecode[] =
 175 {
 176     "Compatibility",
 177     "TypeA",
 178     "TypeB",
 179     "TypeF"
 180 };
 181 
 182 #endif
 183 
 184 
 185 /*
 186  * Base sizes of the raw AML resource descriptors, indexed by resource type.
 187  * Zero indicates a reserved (and therefore invalid) resource type.
 188  */
 189 const UINT8                 AcpiGbl_ResourceAmlSizes[] =
 190 {
 191     /* Small descriptors */
 192 
 193     0,
 194     0,
 195     0,
 196     0,
 197     ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ),
 198     ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA),
 199     ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT),
 200     ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT),
 201     ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO),
 202     ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO),
 203     0,
 204     0,
 205     0,
 206     0,
 207     ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL),
 208     ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG),
 209 
 210     /* Large descriptors */
 211 
 212     0,
 213     ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24),
 214     ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER),
 215     0,
 216     ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE),
 217     ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32),
 218     ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32),
 219     ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32),
 220     ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16),
 221     ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ),
 222     ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64),
 223     ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64)
 224 };
 225 
 226 
 227 /*
 228  * Resource types, used to validate the resource length field.
 229  * The length of fixed-length types must match exactly, variable
 230  * lengths must meet the minimum required length, etc.
 231  * Zero indicates a reserved (and therefore invalid) resource type.
 232  */
 233 static const UINT8          AcpiGbl_ResourceTypes[] =
 234 {
 235     /* Small descriptors */
 236 
 237     0,
 238     0,
 239     0,
 240     0,
 241     ACPI_SMALL_VARIABLE_LENGTH,
 242     ACPI_FIXED_LENGTH,
 243     ACPI_SMALL_VARIABLE_LENGTH,
 244     ACPI_FIXED_LENGTH,
 245     ACPI_FIXED_LENGTH,
 246     ACPI_FIXED_LENGTH,
 247     0,
 248     0,
 249     0,
 250     0,
 251     ACPI_VARIABLE_LENGTH,
 252     ACPI_FIXED_LENGTH,
 253 
 254     /* Large descriptors */
 255 
 256     0,
 257     ACPI_FIXED_LENGTH,
 258     ACPI_FIXED_LENGTH,
 259     0,
 260     ACPI_VARIABLE_LENGTH,
 261     ACPI_FIXED_LENGTH,
 262     ACPI_FIXED_LENGTH,
 263     ACPI_VARIABLE_LENGTH,
 264     ACPI_VARIABLE_LENGTH,
 265     ACPI_VARIABLE_LENGTH,
 266     ACPI_VARIABLE_LENGTH,
 267     ACPI_FIXED_LENGTH
 268 };
 269 
 270 
 271 /*******************************************************************************
 272  *
 273  * FUNCTION:    AcpiUtWalkAmlResources
 274  *
 275  * PARAMETERS:  Aml             - Pointer to the raw AML resource template
 276  *              AmlLength       - Length of the entire template
 277  *              UserFunction    - Called once for each descriptor found. If
 278  *                                NULL, a pointer to the EndTag is returned
 279  *              Context         - Passed to UserFunction
 280  *
 281  * RETURN:      Status
 282  *
 283  * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
 284  *              once for each resource found.
 285  *
 286  ******************************************************************************/
 287 
 288 ACPI_STATUS
 289 AcpiUtWalkAmlResources (
 290     UINT8                   *Aml,
 291     ACPI_SIZE               AmlLength,
 292     ACPI_WALK_AML_CALLBACK  UserFunction,
 293     void                    *Context)
 294 {
 295     ACPI_STATUS             Status;
 296     UINT8                   *EndAml;
 297     UINT8                   ResourceIndex;
 298     UINT32                  Length;
 299     UINT32                  Offset = 0;
 300 
 301 
 302     ACPI_FUNCTION_TRACE (UtWalkAmlResources);
 303 
 304 
 305     /* The absolute minimum resource template is one EndTag descriptor */
 306 
 307     if (AmlLength < sizeof (AML_RESOURCE_END_TAG))
 308     {
 309         return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
 310     }
 311 
 312     /* Point to the end of the resource template buffer */
 313 
 314     EndAml = Aml + AmlLength;
 315 
 316     /* Walk the byte list, abort on any invalid descriptor type or length */
 317 
 318     while (Aml < EndAml)
 319     {
 320         /* Validate the Resource Type and Resource Length */
 321 
 322         Status = AcpiUtValidateResource (Aml, &ResourceIndex);
 323         if (ACPI_FAILURE (Status))
 324         {
 325             return_ACPI_STATUS (Status);
 326         }
 327 
 328         /* Get the length of this descriptor */
 329 
 330         Length = AcpiUtGetDescriptorLength (Aml);
 331 
 332         /* Invoke the user function */
 333 
 334         if (UserFunction)
 335         {
 336             Status = UserFunction (Aml, Length, Offset, ResourceIndex, Context);
 337             if (ACPI_FAILURE (Status))
 338             {
 339                 return (Status);
 340             }
 341         }
 342 
 343         /* An EndTag descriptor terminates this resource template */
 344 
 345         if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_END_TAG)
 346         {
 347             /*
 348              * There must be at least one more byte in the buffer for
 349              * the 2nd byte of the EndTag
 350              */
 351             if ((Aml + 1) >= EndAml)
 352             {
 353                 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
 354             }
 355 
 356             /* Return the pointer to the EndTag if requested */
 357 
 358             if (!UserFunction)
 359             {
 360                 *(void **) Context = Aml;
 361             }
 362 
 363             /* Normal exit */
 364 
 365             return_ACPI_STATUS (AE_OK);
 366         }
 367 
 368         Aml += Length;
 369         Offset += Length;
 370     }
 371 
 372     /* Did not find an EndTag descriptor */
 373 
 374     return (AE_AML_NO_RESOURCE_END_TAG);
 375 }
 376 
 377 
 378 /*******************************************************************************
 379  *
 380  * FUNCTION:    AcpiUtValidateResource
 381  *
 382  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
 383  *              ReturnIndex     - Where the resource index is returned. NULL
 384  *                                if the index is not required.
 385  *
 386  * RETURN:      Status, and optionally the Index into the global resource tables
 387  *
 388  * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
 389  *              Type and Resource Length. Returns an index into the global
 390  *              resource information/dispatch tables for later use.
 391  *
 392  ******************************************************************************/
 393 
 394 ACPI_STATUS
 395 AcpiUtValidateResource (
 396     void                    *Aml,
 397     UINT8                   *ReturnIndex)
 398 {
 399     UINT8                   ResourceType;
 400     UINT8                   ResourceIndex;
 401     ACPI_RS_LENGTH          ResourceLength;
 402     ACPI_RS_LENGTH          MinimumResourceLength;
 403 
 404 
 405     ACPI_FUNCTION_ENTRY ();
 406 
 407 
 408     /*
 409      * 1) Validate the ResourceType field (Byte 0)
 410      */
 411     ResourceType = ACPI_GET8 (Aml);
 412 
 413     /*
 414      * Byte 0 contains the descriptor name (Resource Type)
 415      * Examine the large/small bit in the resource header
 416      */
 417     if (ResourceType & ACPI_RESOURCE_NAME_LARGE)
 418     {
 419         /* Verify the large resource type (name) against the max */
 420 
 421         if (ResourceType > ACPI_RESOURCE_NAME_LARGE_MAX)
 422         {
 423             return (AE_AML_INVALID_RESOURCE_TYPE);
 424         }
 425 
 426         /*
 427          * Large Resource Type -- bits 6:0 contain the name
 428          * Translate range 0x80-0x8B to index range 0x10-0x1B
 429          */
 430         ResourceIndex = (UINT8) (ResourceType - 0x70);
 431     }
 432     else
 433     {
 434         /*
 435          * Small Resource Type -- bits 6:3 contain the name
 436          * Shift range to index range 0x00-0x0F
 437          */
 438         ResourceIndex = (UINT8)
 439             ((ResourceType & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
 440     }
 441 
 442     /* Check validity of the resource type, zero indicates name is invalid */
 443 
 444     if (!AcpiGbl_ResourceTypes[ResourceIndex])
 445     {
 446         return (AE_AML_INVALID_RESOURCE_TYPE);
 447     }
 448 
 449 
 450     /*
 451      * 2) Validate the ResourceLength field. This ensures that the length
 452      *    is at least reasonable, and guarantees that it is non-zero.
 453      */
 454     ResourceLength = AcpiUtGetResourceLength (Aml);
 455     MinimumResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
 456 
 457     /* Validate based upon the type of resource - fixed length or variable */
 458 
 459     switch (AcpiGbl_ResourceTypes[ResourceIndex])
 460     {
 461     case ACPI_FIXED_LENGTH:
 462 
 463         /* Fixed length resource, length must match exactly */
 464 
 465         if (ResourceLength != MinimumResourceLength)
 466         {
 467             return (AE_AML_BAD_RESOURCE_LENGTH);
 468         }
 469         break;
 470 
 471     case ACPI_VARIABLE_LENGTH:
 472 
 473         /* Variable length resource, length must be at least the minimum */
 474 
 475         if (ResourceLength < MinimumResourceLength)
 476         {
 477             return (AE_AML_BAD_RESOURCE_LENGTH);
 478         }
 479         break;
 480 
 481     case ACPI_SMALL_VARIABLE_LENGTH:
 482 
 483         /* Small variable length resource, length can be (Min) or (Min-1) */
 484 
 485         if ((ResourceLength > MinimumResourceLength) ||
 486             (ResourceLength < (MinimumResourceLength - 1)))
 487         {
 488             return (AE_AML_BAD_RESOURCE_LENGTH);
 489         }
 490         break;
 491 
 492     default:
 493 
 494         /* Shouldn't happen (because of validation earlier), but be sure */
 495 
 496         return (AE_AML_INVALID_RESOURCE_TYPE);
 497     }
 498 
 499     /* Optionally return the resource table index */
 500 
 501     if (ReturnIndex)
 502     {
 503         *ReturnIndex = ResourceIndex;
 504     }
 505 
 506     return (AE_OK);
 507 }
 508 
 509 
 510 /*******************************************************************************
 511  *
 512  * FUNCTION:    AcpiUtGetResourceType
 513  *
 514  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
 515  *
 516  * RETURN:      The Resource Type with no extraneous bits (except the
 517  *              Large/Small descriptor bit -- this is left alone)
 518  *
 519  * DESCRIPTION: Extract the Resource Type/Name from the first byte of
 520  *              a resource descriptor.
 521  *
 522  ******************************************************************************/
 523 
 524 UINT8
 525 AcpiUtGetResourceType (
 526     void                    *Aml)
 527 {
 528     ACPI_FUNCTION_ENTRY ();
 529 
 530 
 531     /*
 532      * Byte 0 contains the descriptor name (Resource Type)
 533      * Examine the large/small bit in the resource header
 534      */
 535     if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
 536     {
 537         /* Large Resource Type -- bits 6:0 contain the name */
 538 
 539         return (ACPI_GET8 (Aml));
 540     }
 541     else
 542     {
 543         /* Small Resource Type -- bits 6:3 contain the name */
 544 
 545         return ((UINT8) (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
 546     }
 547 }
 548 
 549 
 550 /*******************************************************************************
 551  *
 552  * FUNCTION:    AcpiUtGetResourceLength
 553  *
 554  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
 555  *
 556  * RETURN:      Byte Length
 557  *
 558  * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
 559  *              definition, this does not include the size of the descriptor
 560  *              header or the length field itself.
 561  *
 562  ******************************************************************************/
 563 
 564 UINT16
 565 AcpiUtGetResourceLength (
 566     void                    *Aml)
 567 {
 568     ACPI_RS_LENGTH          ResourceLength;
 569 
 570 
 571     ACPI_FUNCTION_ENTRY ();
 572 
 573 
 574     /*
 575      * Byte 0 contains the descriptor name (Resource Type)
 576      * Examine the large/small bit in the resource header
 577      */
 578     if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
 579     {
 580         /* Large Resource type -- bytes 1-2 contain the 16-bit length */
 581 
 582         ACPI_MOVE_16_TO_16 (&ResourceLength, ACPI_ADD_PTR (UINT8, Aml, 1));
 583 
 584     }
 585     else
 586     {
 587         /* Small Resource type -- bits 2:0 of byte 0 contain the length */
 588 
 589         ResourceLength = (UINT16) (ACPI_GET8 (Aml) &
 590                                     ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
 591     }
 592 
 593     return (ResourceLength);
 594 }
 595 
 596 
 597 /*******************************************************************************
 598  *
 599  * FUNCTION:    AcpiUtGetResourceHeaderLength
 600  *
 601  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
 602  *
 603  * RETURN:      Length of the AML header (depends on large/small descriptor)
 604  *
 605  * DESCRIPTION: Get the length of the header for this resource.
 606  *
 607  ******************************************************************************/
 608 
 609 UINT8
 610 AcpiUtGetResourceHeaderLength (
 611     void                    *Aml)
 612 {
 613     ACPI_FUNCTION_ENTRY ();
 614 
 615 
 616     /* Examine the large/small bit in the resource header */
 617 
 618     if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE)
 619     {
 620         return (sizeof (AML_RESOURCE_LARGE_HEADER));
 621     }
 622     else
 623     {
 624         return (sizeof (AML_RESOURCE_SMALL_HEADER));
 625     }
 626 }
 627 
 628 
 629 /*******************************************************************************
 630  *
 631  * FUNCTION:    AcpiUtGetDescriptorLength
 632  *
 633  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
 634  *
 635  * RETURN:      Byte length
 636  *
 637  * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
 638  *              length of the descriptor header and the length field itself.
 639  *              Used to walk descriptor lists.
 640  *
 641  ******************************************************************************/
 642 
 643 UINT32
 644 AcpiUtGetDescriptorLength (
 645     void                    *Aml)
 646 {
 647     ACPI_FUNCTION_ENTRY ();
 648 
 649 
 650     /*
 651      * Get the Resource Length (does not include header length) and add
 652      * the header length (depends on if this is a small or large resource)
 653      */
 654     return (AcpiUtGetResourceLength (Aml) +
 655             AcpiUtGetResourceHeaderLength (Aml));
 656 }
 657 
 658 
 659 /*******************************************************************************
 660  *
 661  * FUNCTION:    AcpiUtGetResourceEndTag
 662  *
 663  * PARAMETERS:  ObjDesc         - The resource template buffer object
 664  *              EndTag          - Where the pointer to the EndTag is returned
 665  *
 666  * RETURN:      Status, pointer to the end tag
 667  *
 668  * DESCRIPTION: Find the EndTag resource descriptor in an AML resource template
 669  *              Note: allows a buffer length of zero.
 670  *
 671  ******************************************************************************/
 672 
 673 ACPI_STATUS
 674 AcpiUtGetResourceEndTag (
 675     ACPI_OPERAND_OBJECT     *ObjDesc,
 676     UINT8                   **EndTag)
 677 {
 678     ACPI_STATUS             Status;
 679 
 680 
 681     ACPI_FUNCTION_TRACE (UtGetResourceEndTag);
 682 
 683 
 684     /* Allow a buffer length of zero */
 685 
 686     if (!ObjDesc->Buffer.Length)
 687     {
 688         *EndTag = ObjDesc->Buffer.Pointer;
 689         return_ACPI_STATUS (AE_OK);
 690     }
 691 
 692     /* Validate the template and get a pointer to the EndTag */
 693 
 694     Status = AcpiUtWalkAmlResources (ObjDesc->Buffer.Pointer,
 695                 ObjDesc->Buffer.Length, NULL, EndTag);
 696 
 697     return_ACPI_STATUS (Status);
 698 }
 699 
 700