Home | History | Annotate | Line # | Download | only in resources
rscalc.c revision 1.1.1.14
      1 /*******************************************************************************
      2  *
      3  * Module Name: rscalc - Calculate stream and list lengths
      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 "acpi.h"
     45 #include "accommon.h"
     46 #include "acresrc.h"
     47 #include "acnamesp.h"
     48 
     49 
     50 #define _COMPONENT          ACPI_RESOURCES
     51         ACPI_MODULE_NAME    ("rscalc")
     52 
     53 
     54 /* Local prototypes */
     55 
     56 static UINT8
     57 AcpiRsCountSetBits (
     58     UINT16                  BitField);
     59 
     60 static ACPI_RS_LENGTH
     61 AcpiRsStructOptionLength (
     62     ACPI_RESOURCE_SOURCE    *ResourceSource);
     63 
     64 static UINT32
     65 AcpiRsStreamOptionLength (
     66     UINT32                  ResourceLength,
     67     UINT32                  MinimumTotalLength);
     68 
     69 
     70 /*******************************************************************************
     71  *
     72  * FUNCTION:    AcpiRsCountSetBits
     73  *
     74  * PARAMETERS:  BitField        - Field in which to count bits
     75  *
     76  * RETURN:      Number of bits set within the field
     77  *
     78  * DESCRIPTION: Count the number of bits set in a resource field. Used for
     79  *              (Short descriptor) interrupt and DMA lists.
     80  *
     81  ******************************************************************************/
     82 
     83 static UINT8
     84 AcpiRsCountSetBits (
     85     UINT16                  BitField)
     86 {
     87     UINT8                   BitsSet;
     88 
     89 
     90     ACPI_FUNCTION_ENTRY ();
     91 
     92 
     93     for (BitsSet = 0; BitField; BitsSet++)
     94     {
     95         /* Zero the least significant bit that is set */
     96 
     97         BitField &= (UINT16) (BitField - 1);
     98     }
     99 
    100     return (BitsSet);
    101 }
    102 
    103 
    104 /*******************************************************************************
    105  *
    106  * FUNCTION:    AcpiRsStructOptionLength
    107  *
    108  * PARAMETERS:  ResourceSource      - Pointer to optional descriptor field
    109  *
    110  * RETURN:      Status
    111  *
    112  * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
    113  *              ResourceSource fields in some Large descriptors. Used during
    114  *              list-to-stream conversion
    115  *
    116  ******************************************************************************/
    117 
    118 static ACPI_RS_LENGTH
    119 AcpiRsStructOptionLength (
    120     ACPI_RESOURCE_SOURCE    *ResourceSource)
    121 {
    122     ACPI_FUNCTION_ENTRY ();
    123 
    124 
    125     /*
    126      * If the ResourceSource string is valid, return the size of the string
    127      * (StringLength includes the NULL terminator) plus the size of the
    128      * ResourceSourceIndex (1).
    129      */
    130     if (ResourceSource->StringPtr)
    131     {
    132         return ((ACPI_RS_LENGTH) (ResourceSource->StringLength + 1));
    133     }
    134 
    135     return (0);
    136 }
    137 
    138 
    139 /*******************************************************************************
    140  *
    141  * FUNCTION:    AcpiRsStreamOptionLength
    142  *
    143  * PARAMETERS:  ResourceLength      - Length from the resource header
    144  *              MinimumTotalLength  - Minimum length of this resource, before
    145  *                                    any optional fields. Includes header size
    146  *
    147  * RETURN:      Length of optional string (0 if no string present)
    148  *
    149  * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
    150  *              ResourceSource fields in some Large descriptors. Used during
    151  *              stream-to-list conversion
    152  *
    153  ******************************************************************************/
    154 
    155 static UINT32
    156 AcpiRsStreamOptionLength (
    157     UINT32                  ResourceLength,
    158     UINT32                  MinimumAmlResourceLength)
    159 {
    160     UINT32                  StringLength = 0;
    161 
    162 
    163     ACPI_FUNCTION_ENTRY ();
    164 
    165 
    166     /*
    167      * The ResourceSourceIndex and ResourceSource are optional elements of
    168      * some Large-type resource descriptors.
    169      */
    170 
    171     /*
    172      * If the length of the actual resource descriptor is greater than the
    173      * ACPI spec-defined minimum length, it means that a ResourceSourceIndex
    174      * exists and is followed by a (required) null terminated string. The
    175      * string length (including the null terminator) is the resource length
    176      * minus the minimum length, minus one byte for the ResourceSourceIndex
    177      * itself.
    178      */
    179     if (ResourceLength > MinimumAmlResourceLength)
    180     {
    181         /* Compute the length of the optional string */
    182 
    183         StringLength = ResourceLength - MinimumAmlResourceLength - 1;
    184     }
    185 
    186     /*
    187      * Round the length up to a multiple of the native word in order to
    188      * guarantee that the entire resource descriptor is native word aligned
    189      */
    190     return ((UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (StringLength));
    191 }
    192 
    193 
    194 /*******************************************************************************
    195  *
    196  * FUNCTION:    AcpiRsGetAmlLength
    197  *
    198  * PARAMETERS:  Resource            - Pointer to the resource linked list
    199  *              ResourceListSize    - Size of the resource linked list
    200  *              SizeNeeded          - Where the required size is returned
    201  *
    202  * RETURN:      Status
    203  *
    204  * DESCRIPTION: Takes a linked list of internal resource descriptors and
    205  *              calculates the size buffer needed to hold the corresponding
    206  *              external resource byte stream.
    207  *
    208  ******************************************************************************/
    209 
    210 ACPI_STATUS
    211 AcpiRsGetAmlLength (
    212     ACPI_RESOURCE           *Resource,
    213     ACPI_SIZE               ResourceListSize,
    214     ACPI_SIZE               *SizeNeeded)
    215 {
    216     ACPI_SIZE               AmlSizeNeeded = 0;
    217     ACPI_RESOURCE           *ResourceEnd;
    218     ACPI_RS_LENGTH          TotalSize;
    219 
    220 
    221     ACPI_FUNCTION_TRACE (RsGetAmlLength);
    222 
    223 
    224     /* Traverse entire list of internal resource descriptors */
    225 
    226     ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, ResourceListSize);
    227     while (Resource < ResourceEnd)
    228     {
    229         /* Validate the descriptor type */
    230 
    231         if (Resource->Type > ACPI_RESOURCE_TYPE_MAX)
    232         {
    233             return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
    234         }
    235 
    236         /* Sanity check the length. It must not be zero, or we loop forever */
    237 
    238         if (!Resource->Length)
    239         {
    240             return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
    241         }
    242 
    243         /* Get the base size of the (external stream) resource descriptor */
    244 
    245         TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type];
    246 
    247         /*
    248          * Augment the base size for descriptors with optional and/or
    249          * variable-length fields
    250          */
    251         switch (Resource->Type)
    252         {
    253         case ACPI_RESOURCE_TYPE_IRQ:
    254 
    255             /* Length can be 3 or 2 */
    256 
    257             if (Resource->Data.Irq.DescriptorLength == 2)
    258             {
    259                 TotalSize--;
    260             }
    261             break;
    262 
    263 
    264         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
    265 
    266             /* Length can be 1 or 0 */
    267 
    268             if (Resource->Data.Irq.DescriptorLength == 0)
    269             {
    270                 TotalSize--;
    271             }
    272             break;
    273 
    274 
    275         case ACPI_RESOURCE_TYPE_VENDOR:
    276             /*
    277              * Vendor Defined Resource:
    278              * For a Vendor Specific resource, if the Length is between 1 and 7
    279              * it will be created as a Small Resource data type, otherwise it
    280              * is a Large Resource data type.
    281              */
    282             if (Resource->Data.Vendor.ByteLength > 7)
    283             {
    284                 /* Base size of a Large resource descriptor */
    285 
    286                 TotalSize = sizeof (AML_RESOURCE_LARGE_HEADER);
    287             }
    288 
    289             /* Add the size of the vendor-specific data */
    290 
    291             TotalSize = (ACPI_RS_LENGTH)
    292                 (TotalSize + Resource->Data.Vendor.ByteLength);
    293             break;
    294 
    295 
    296         case ACPI_RESOURCE_TYPE_END_TAG:
    297             /*
    298              * End Tag:
    299              * We are done -- return the accumulated total size.
    300              */
    301             *SizeNeeded = AmlSizeNeeded + TotalSize;
    302 
    303             /* Normal exit */
    304 
    305             return_ACPI_STATUS (AE_OK);
    306 
    307 
    308         case ACPI_RESOURCE_TYPE_ADDRESS16:
    309             /*
    310              * 16-Bit Address Resource:
    311              * Add the size of the optional ResourceSource info
    312              */
    313             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    314                 AcpiRsStructOptionLength (
    315                     &Resource->Data.Address16.ResourceSource));
    316             break;
    317 
    318 
    319         case ACPI_RESOURCE_TYPE_ADDRESS32:
    320             /*
    321              * 32-Bit Address Resource:
    322              * Add the size of the optional ResourceSource info
    323              */
    324             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    325                 AcpiRsStructOptionLength (
    326                     &Resource->Data.Address32.ResourceSource));
    327             break;
    328 
    329 
    330         case ACPI_RESOURCE_TYPE_ADDRESS64:
    331             /*
    332              * 64-Bit Address Resource:
    333              * Add the size of the optional ResourceSource info
    334              */
    335             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    336                 AcpiRsStructOptionLength (
    337                     &Resource->Data.Address64.ResourceSource));
    338             break;
    339 
    340 
    341         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
    342             /*
    343              * Extended IRQ Resource:
    344              * Add the size of each additional optional interrupt beyond the
    345              * required 1 (4 bytes for each UINT32 interrupt number)
    346              */
    347             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    348                 ((Resource->Data.ExtendedIrq.InterruptCount - 1) * 4) +
    349 
    350                 /* Add the size of the optional ResourceSource info */
    351 
    352                 AcpiRsStructOptionLength (
    353                     &Resource->Data.ExtendedIrq.ResourceSource));
    354             break;
    355 
    356 
    357         case ACPI_RESOURCE_TYPE_GPIO:
    358 
    359             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    360                 (Resource->Data.Gpio.PinTableLength * 2) +
    361                 Resource->Data.Gpio.ResourceSource.StringLength +
    362                 Resource->Data.Gpio.VendorLength);
    363 
    364             break;
    365 
    366         case ACPI_RESOURCE_TYPE_PIN_FUNCTION:
    367 
    368             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    369                 (Resource->Data.PinFunction.PinTableLength * 2) +
    370                 Resource->Data.PinFunction.ResourceSource.StringLength +
    371                 Resource->Data.PinFunction.VendorLength);
    372 
    373             break;
    374 
    375         case ACPI_RESOURCE_TYPE_CLOCK_INPUT:
    376 
    377             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    378                 Resource->Data.ClockInput.ResourceSource.StringLength);
    379 
    380             break;
    381 
    382 
    383         case ACPI_RESOURCE_TYPE_SERIAL_BUS:
    384 
    385             TotalSize = AcpiGbl_AmlResourceSerialBusSizes [
    386                 Resource->Data.CommonSerialBus.Type];
    387 
    388             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    389                 Resource->Data.I2cSerialBus.ResourceSource.StringLength +
    390                 Resource->Data.I2cSerialBus.VendorLength);
    391 
    392             break;
    393 
    394         case ACPI_RESOURCE_TYPE_PIN_CONFIG:
    395 
    396             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    397                 (Resource->Data.PinConfig.PinTableLength * 2) +
    398                 Resource->Data.PinConfig.ResourceSource.StringLength +
    399                 Resource->Data.PinConfig.VendorLength);
    400 
    401             break;
    402 
    403         case ACPI_RESOURCE_TYPE_PIN_GROUP:
    404 
    405             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    406                 (Resource->Data.PinGroup.PinTableLength * 2) +
    407                 Resource->Data.PinGroup.ResourceLabel.StringLength +
    408                 Resource->Data.PinGroup.VendorLength);
    409 
    410             break;
    411 
    412         case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION:
    413 
    414             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    415                 Resource->Data.PinGroupFunction.ResourceSource.StringLength +
    416                 Resource->Data.PinGroupFunction.ResourceSourceLabel.StringLength +
    417                 Resource->Data.PinGroupFunction.VendorLength);
    418 
    419             break;
    420 
    421         case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG:
    422 
    423             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
    424                 Resource->Data.PinGroupConfig.ResourceSource.StringLength +
    425                 Resource->Data.PinGroupConfig.ResourceSourceLabel.StringLength +
    426                 Resource->Data.PinGroupConfig.VendorLength);
    427 
    428             break;
    429 
    430         default:
    431 
    432             break;
    433         }
    434 
    435         /* Update the total */
    436 
    437         AmlSizeNeeded += TotalSize;
    438 
    439         /* Point to the next object */
    440 
    441         Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length);
    442     }
    443 
    444     /* Did not find an EndTag resource descriptor */
    445 
    446     return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
    447 }
    448 
    449 
    450 /*******************************************************************************
    451  *
    452  * FUNCTION:    AcpiRsGetListLength
    453  *
    454  * PARAMETERS:  AmlBuffer           - Pointer to the resource byte stream
    455  *              AmlBufferLength     - Size of AmlBuffer
    456  *              SizeNeeded          - Where the size needed is returned
    457  *
    458  * RETURN:      Status
    459  *
    460  * DESCRIPTION: Takes an external resource byte stream and calculates the size
    461  *              buffer needed to hold the corresponding internal resource
    462  *              descriptor linked list.
    463  *
    464  ******************************************************************************/
    465 
    466 ACPI_STATUS
    467 AcpiRsGetListLength (
    468     UINT8                   *AmlBuffer,
    469     UINT32                  AmlBufferLength,
    470     ACPI_SIZE               *SizeNeeded)
    471 {
    472     ACPI_STATUS             Status;
    473     UINT8                   *EndAml;
    474     UINT8                   *Buffer;
    475     UINT32                  BufferSize;
    476     UINT16                  Temp16;
    477     UINT16                  ResourceLength;
    478     UINT32                  ExtraStructBytes;
    479     UINT8                   ResourceIndex;
    480     UINT8                   MinimumAmlResourceLength;
    481     AML_RESOURCE            *AmlResource;
    482 
    483 
    484     ACPI_FUNCTION_TRACE (RsGetListLength);
    485 
    486 
    487     *SizeNeeded = ACPI_RS_SIZE_MIN;         /* Minimum size is one EndTag */
    488     EndAml = AmlBuffer + AmlBufferLength;
    489 
    490     /* Walk the list of AML resource descriptors */
    491 
    492     while (AmlBuffer < EndAml)
    493     {
    494         /* Validate the Resource Type and Resource Length */
    495 
    496         Status = AcpiUtValidateResource (NULL, AmlBuffer, &ResourceIndex);
    497         if (ACPI_FAILURE (Status))
    498         {
    499             /*
    500              * Exit on failure. Cannot continue because the descriptor length
    501              * may be bogus also.
    502              */
    503             return_ACPI_STATUS (Status);
    504         }
    505 
    506         AmlResource = (void *) AmlBuffer;
    507 
    508         /* Get the resource length and base (minimum) AML size */
    509 
    510         ResourceLength = AcpiUtGetResourceLength (AmlBuffer);
    511         MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
    512 
    513         /*
    514          * Augment the size for descriptors with optional
    515          * and/or variable length fields
    516          */
    517         ExtraStructBytes = 0;
    518         Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer);
    519 
    520         switch (AcpiUtGetResourceType (AmlBuffer))
    521         {
    522         case ACPI_RESOURCE_NAME_IRQ:
    523             /*
    524              * IRQ Resource:
    525              * Get the number of bits set in the 16-bit IRQ mask
    526              */
    527             ACPI_MOVE_16_TO_16 (&Temp16, Buffer);
    528             ExtraStructBytes = AcpiRsCountSetBits (Temp16);
    529             break;
    530 
    531 
    532         case ACPI_RESOURCE_NAME_DMA:
    533             /*
    534              * DMA Resource:
    535              * Get the number of bits set in the 8-bit DMA mask
    536              */
    537             ExtraStructBytes = AcpiRsCountSetBits (*Buffer);
    538             break;
    539 
    540 
    541         case ACPI_RESOURCE_NAME_VENDOR_SMALL:
    542         case ACPI_RESOURCE_NAME_VENDOR_LARGE:
    543             /*
    544              * Vendor Resource:
    545              * Get the number of vendor data bytes
    546              */
    547             ExtraStructBytes = ResourceLength;
    548 
    549             /*
    550              * There is already one byte included in the minimum
    551              * descriptor size. If there are extra struct bytes,
    552              * subtract one from the count.
    553              */
    554             if (ExtraStructBytes)
    555             {
    556                 ExtraStructBytes--;
    557             }
    558             break;
    559 
    560 
    561         case ACPI_RESOURCE_NAME_END_TAG:
    562             /*
    563              * End Tag: This is the normal exit
    564              */
    565             return_ACPI_STATUS (AE_OK);
    566 
    567 
    568         case ACPI_RESOURCE_NAME_ADDRESS32:
    569         case ACPI_RESOURCE_NAME_ADDRESS16:
    570         case ACPI_RESOURCE_NAME_ADDRESS64:
    571             /*
    572              * Address Resource:
    573              * Add the size of the optional ResourceSource
    574              */
    575             ExtraStructBytes = AcpiRsStreamOptionLength (
    576                 ResourceLength, MinimumAmlResourceLength);
    577             break;
    578 
    579 
    580         case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
    581             /*
    582              * Extended IRQ Resource:
    583              * Using the InterruptTableLength, add 4 bytes for each additional
    584              * interrupt. Note: at least one interrupt is required and is
    585              * included in the minimum descriptor size (reason for the -1)
    586              */
    587             ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32);
    588 
    589             /* Add the size of the optional ResourceSource */
    590 
    591             ExtraStructBytes += AcpiRsStreamOptionLength (
    592                 ResourceLength - ExtraStructBytes, MinimumAmlResourceLength);
    593             break;
    594 
    595         case ACPI_RESOURCE_NAME_GPIO:
    596 
    597             /* Vendor data is optional */
    598 
    599             if (AmlResource->Gpio.VendorLength)
    600             {
    601                 ExtraStructBytes +=
    602                     AmlResource->Gpio.VendorOffset -
    603                     AmlResource->Gpio.PinTableOffset +
    604                     AmlResource->Gpio.VendorLength;
    605             }
    606             else
    607             {
    608                 ExtraStructBytes +=
    609                     AmlResource->LargeHeader.ResourceLength +
    610                     sizeof (AML_RESOURCE_LARGE_HEADER) -
    611                     AmlResource->Gpio.PinTableOffset;
    612             }
    613             break;
    614 
    615         case ACPI_RESOURCE_NAME_PIN_FUNCTION:
    616 
    617             /* Vendor data is optional */
    618 
    619             if (AmlResource->PinFunction.VendorLength)
    620             {
    621                 ExtraStructBytes +=
    622                     AmlResource->PinFunction.VendorOffset -
    623                     AmlResource->PinFunction.PinTableOffset +
    624                     AmlResource->PinFunction.VendorLength;
    625             }
    626             else
    627             {
    628                 ExtraStructBytes +=
    629                     AmlResource->LargeHeader.ResourceLength +
    630                     sizeof (AML_RESOURCE_LARGE_HEADER) -
    631                     AmlResource->PinFunction.PinTableOffset;
    632             }
    633             break;
    634 
    635         case ACPI_RESOURCE_NAME_SERIAL_BUS: {
    636             /* Avoid undefined behavior: member access within misaligned address */
    637 
    638             AML_RESOURCE_COMMON_SERIALBUS CommonSerialBus;
    639             memcpy(&CommonSerialBus, AmlResource, sizeof(CommonSerialBus));
    640 
    641             MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[
    642                 CommonSerialBus.Type];
    643             ExtraStructBytes +=
    644                 CommonSerialBus.ResourceLength -
    645                 MinimumAmlResourceLength;
    646             break;
    647         }
    648 
    649         case ACPI_RESOURCE_NAME_PIN_CONFIG:
    650 
    651             /* Vendor data is optional */
    652 
    653             if (AmlResource->PinConfig.VendorLength)
    654             {
    655                 ExtraStructBytes +=
    656                     AmlResource->PinConfig.VendorOffset -
    657                     AmlResource->PinConfig.PinTableOffset +
    658                     AmlResource->PinConfig.VendorLength;
    659             }
    660             else
    661             {
    662                 ExtraStructBytes +=
    663                     AmlResource->LargeHeader.ResourceLength +
    664                     sizeof (AML_RESOURCE_LARGE_HEADER) -
    665                     AmlResource->PinConfig.PinTableOffset;
    666             }
    667             break;
    668 
    669         case ACPI_RESOURCE_NAME_PIN_GROUP:
    670 
    671             ExtraStructBytes +=
    672                 AmlResource->PinGroup.VendorOffset -
    673                 AmlResource->PinGroup.PinTableOffset +
    674                 AmlResource->PinGroup.VendorLength;
    675 
    676             break;
    677 
    678         case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION:
    679 
    680             ExtraStructBytes +=
    681                 AmlResource->PinGroupFunction.VendorOffset -
    682                 AmlResource->PinGroupFunction.ResSourceOffset +
    683                 AmlResource->PinGroupFunction.VendorLength;
    684 
    685             break;
    686 
    687         case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG:
    688 
    689             ExtraStructBytes +=
    690                 AmlResource->PinGroupConfig.VendorOffset -
    691                 AmlResource->PinGroupConfig.ResSourceOffset +
    692                 AmlResource->PinGroupConfig.VendorLength;
    693 
    694             break;
    695 
    696         case ACPI_RESOURCE_NAME_CLOCK_INPUT:
    697             ExtraStructBytes = AcpiRsStreamOptionLength (
    698                 ResourceLength, MinimumAmlResourceLength);
    699 
    700             break;
    701 
    702         default:
    703 
    704             break;
    705         }
    706 
    707         /*
    708          * Update the required buffer size for the internal descriptor structs
    709          *
    710          * Important: Round the size up for the appropriate alignment. This
    711          * is a requirement on IA64.
    712          */
    713         if (AcpiUtGetResourceType (AmlBuffer) ==
    714             ACPI_RESOURCE_NAME_SERIAL_BUS)
    715         {
    716             /* Avoid undefined behavior: member access within misaligned address */
    717 
    718             AML_RESOURCE_COMMON_SERIALBUS CommonSerialBus;
    719             memcpy(&CommonSerialBus, AmlResource, sizeof(CommonSerialBus));
    720 
    721             BufferSize = AcpiGbl_ResourceStructSerialBusSizes[
    722                 CommonSerialBus.Type] + ExtraStructBytes;
    723         }
    724         else
    725         {
    726             BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] +
    727                 ExtraStructBytes;
    728         }
    729 
    730         BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize);
    731         *SizeNeeded += BufferSize;
    732 
    733         ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES,
    734             "Type %.2X, AmlLength %.2X InternalLength %.2X%8X\n",
    735             AcpiUtGetResourceType (AmlBuffer),
    736             AcpiUtGetDescriptorLength (AmlBuffer), ACPI_FORMAT_UINT64(*SizeNeeded)));
    737 
    738         /*
    739          * Point to the next resource within the AML stream using the length
    740          * contained in the resource descriptor header
    741          */
    742         AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer);
    743     }
    744 
    745     /* Did not find an EndTag resource descriptor */
    746 
    747     return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
    748 }
    749 
    750 
    751 /*******************************************************************************
    752  *
    753  * FUNCTION:    AcpiRsGetPciRoutingTableLength
    754  *
    755  * PARAMETERS:  PackageObject           - Pointer to the package object
    756  *              BufferSizeNeeded        - UINT32 pointer of the size buffer
    757  *                                        needed to properly return the
    758  *                                        parsed data
    759  *
    760  * RETURN:      Status
    761  *
    762  * DESCRIPTION: Given a package representing a PCI routing table, this
    763  *              calculates the size of the corresponding linked list of
    764  *              descriptions.
    765  *
    766  ******************************************************************************/
    767 
    768 ACPI_STATUS
    769 AcpiRsGetPciRoutingTableLength (
    770     ACPI_OPERAND_OBJECT     *PackageObject,
    771     ACPI_SIZE               *BufferSizeNeeded)
    772 {
    773     UINT32                  NumberOfElements;
    774     ACPI_SIZE               TempSizeNeeded = 0;
    775     ACPI_OPERAND_OBJECT     **TopObjectList;
    776     UINT32                  Index;
    777     ACPI_OPERAND_OBJECT     *PackageElement;
    778     ACPI_OPERAND_OBJECT     **SubObjectList;
    779     BOOLEAN                 NameFound;
    780     UINT32                  TableIndex;
    781 
    782 
    783     ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength);
    784 
    785 
    786     NumberOfElements = PackageObject->Package.Count;
    787 
    788     /*
    789      * Calculate the size of the return buffer.
    790      * The base size is the number of elements * the sizes of the
    791      * structures. Additional space for the strings is added below.
    792      * The minus one is to subtract the size of the UINT8 Source[1]
    793      * member because it is added below.
    794      *
    795      * But each PRT_ENTRY structure has a pointer to a string and
    796      * the size of that string must be found.
    797      */
    798     TopObjectList = PackageObject->Package.Elements;
    799 
    800     for (Index = 0; Index < NumberOfElements; Index++)
    801     {
    802         /* Dereference the subpackage */
    803 
    804         PackageElement = *TopObjectList;
    805 
    806         /* We must have a valid Package object */
    807 
    808         if (!PackageElement ||
    809             (PackageElement->Common.Type != ACPI_TYPE_PACKAGE))
    810         {
    811             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
    812         }
    813 
    814         /*
    815          * The SubObjectList will now point to an array of the
    816          * four IRQ elements: Address, Pin, Source and SourceIndex
    817          */
    818         SubObjectList = PackageElement->Package.Elements;
    819 
    820         /* Scan the IrqTableElements for the Source Name String */
    821 
    822         NameFound = FALSE;
    823 
    824         for (TableIndex = 0;
    825              TableIndex < PackageElement->Package.Count && !NameFound;
    826              TableIndex++)
    827         {
    828             if (*SubObjectList && /* Null object allowed */
    829 
    830                 ((ACPI_TYPE_STRING ==
    831                     (*SubObjectList)->Common.Type) ||
    832 
    833                 ((ACPI_TYPE_LOCAL_REFERENCE ==
    834                     (*SubObjectList)->Common.Type) &&
    835 
    836                     ((*SubObjectList)->Reference.Class ==
    837                         ACPI_REFCLASS_NAME))))
    838             {
    839                 NameFound = TRUE;
    840             }
    841             else
    842             {
    843                 /* Look at the next element */
    844 
    845                 SubObjectList++;
    846             }
    847         }
    848 
    849         TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);
    850 
    851         /* Was a String type found? */
    852 
    853         if (NameFound)
    854         {
    855             if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING)
    856             {
    857                 /*
    858                  * The length String.Length field does not include the
    859                  * terminating NULL, add 1
    860                  */
    861                 TempSizeNeeded += ((ACPI_SIZE)
    862                     (*SubObjectList)->String.Length + 1);
    863             }
    864             else
    865             {
    866                 TempSizeNeeded += AcpiNsGetPathnameLength (
    867                     (*SubObjectList)->Reference.Node);
    868             }
    869         }
    870         else
    871         {
    872             /*
    873              * If no name was found, then this is a NULL, which is
    874              * translated as a UINT32 zero.
    875              */
    876             TempSizeNeeded += sizeof (UINT32);
    877         }
    878 
    879         /* Round up the size since each element must be aligned */
    880 
    881         TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded);
    882 
    883         /* Point to the next ACPI_OPERAND_OBJECT */
    884 
    885         TopObjectList++;
    886     }
    887 
    888     /*
    889      * Add an extra element to the end of the list, essentially a
    890      * NULL terminator
    891      */
    892     *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE);
    893     return_ACPI_STATUS (AE_OK);
    894 }
    895