Home | History | Annotate | Line # | Download | only in utilities
utresrc.c revision 1.1.1.2
      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 
    701