Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:03

0001 /*******************************************************************************
0002  *
0003  * Module Name: rscalc - Calculate stream and list lengths
0004  *
0005  ******************************************************************************/
0006 
0007 /******************************************************************************
0008  *
0009  * 1. Copyright Notice
0010  *
0011  * Some or all of this work - Copyright (c) 1999 - 2024, Intel Corp.
0012  * All rights reserved.
0013  *
0014  * 2. License
0015  *
0016  * 2.1. This is your license from Intel Corp. under its intellectual property
0017  * rights. You may have additional license terms from the party that provided
0018  * you this software, covering your right to use that party's intellectual
0019  * property rights.
0020  *
0021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0022  * copy of the source code appearing in this file ("Covered Code") an
0023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0024  * base code distributed originally by Intel ("Original Intel Code") to copy,
0025  * make derivatives, distribute, use and display any portion of the Covered
0026  * Code in any form, with the right to sublicense such rights; and
0027  *
0028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0029  * license (with the right to sublicense), under only those claims of Intel
0030  * patents that are infringed by the Original Intel Code, to make, use, sell,
0031  * offer to sell, and import the Covered Code and derivative works thereof
0032  * solely to the minimum extent necessary to exercise the above copyright
0033  * license, and in no event shall the patent license extend to any additions
0034  * to or modifications of the Original Intel Code. No other license or right
0035  * is granted directly or by implication, estoppel or otherwise;
0036  *
0037  * The above copyright and patent license is granted only if the following
0038  * conditions are met:
0039  *
0040  * 3. Conditions
0041  *
0042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0043  * Redistribution of source code of any substantial portion of the Covered
0044  * Code or modification with rights to further distribute source must include
0045  * the above Copyright Notice, the above License, this list of Conditions,
0046  * and the following Disclaimer and Export Compliance provision. In addition,
0047  * Licensee must cause all Covered Code to which Licensee contributes to
0048  * contain a file documenting the changes Licensee made to create that Covered
0049  * Code and the date of any change. Licensee must include in that file the
0050  * documentation of any changes made by any predecessor Licensee. Licensee
0051  * must include a prominent statement that the modification is derived,
0052  * directly or indirectly, from Original Intel Code.
0053  *
0054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0055  * Redistribution of source code of any substantial portion of the Covered
0056  * Code or modification without rights to further distribute source must
0057  * include the following Disclaimer and Export Compliance provision in the
0058  * documentation and/or other materials provided with distribution. In
0059  * addition, Licensee may not authorize further sublicense of source of any
0060  * portion of the Covered Code, and must include terms to the effect that the
0061  * license from Licensee to its licensee is limited to the intellectual
0062  * property embodied in the software Licensee provides to its licensee, and
0063  * not to intellectual property embodied in modifications its licensee may
0064  * make.
0065  *
0066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0067  * substantial portion of the Covered Code or modification must reproduce the
0068  * above Copyright Notice, and the following Disclaimer and Export Compliance
0069  * provision in the documentation and/or other materials provided with the
0070  * distribution.
0071  *
0072  * 3.4. Intel retains all right, title, and interest in and to the Original
0073  * Intel Code.
0074  *
0075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0076  * Intel shall be used in advertising or otherwise to promote the sale, use or
0077  * other dealings in products derived from or relating to the Covered Code
0078  * without prior written authorization from Intel.
0079  *
0080  * 4. Disclaimer and Export Compliance
0081  *
0082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0083  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
0085  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
0086  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
0087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0088  * PARTICULAR PURPOSE.
0089  *
0090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
0096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0097  * LIMITED REMEDY.
0098  *
0099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0100  * software or system incorporating such software without first obtaining any
0101  * required license or other approval from the U. S. Department of Commerce or
0102  * any other agency or department of the United States Government. In the
0103  * event Licensee exports any such software from the United States or
0104  * re-exports any such software from a foreign destination, Licensee shall
0105  * ensure that the distribution and export/re-export of the software is in
0106  * compliance with all laws, regulations, orders, or other restrictions of the
0107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0108  * any of its subsidiaries will export/re-export any technical data, process,
0109  * software, or service, directly or indirectly, to any country for which the
0110  * United States government or any agency thereof requires an export license,
0111  * other governmental approval, or letter of assurance, without first obtaining
0112  * such license, approval or letter.
0113  *
0114  *****************************************************************************
0115  *
0116  * Alternatively, you may choose to be licensed under the terms of the
0117  * following license:
0118  *
0119  * Redistribution and use in source and binary forms, with or without
0120  * modification, are permitted provided that the following conditions
0121  * are met:
0122  * 1. Redistributions of source code must retain the above copyright
0123  *    notice, this list of conditions, and the following disclaimer,
0124  *    without modification.
0125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
0126  *    substantially similar to the "NO WARRANTY" disclaimer below
0127  *    ("Disclaimer") and any redistribution must be conditioned upon
0128  *    including a substantially similar Disclaimer requirement for further
0129  *    binary redistribution.
0130  * 3. Neither the names of the above-listed copyright holders nor the names
0131  *    of any contributors may be used to endorse or promote products derived
0132  *    from this software without specific prior written permission.
0133  *
0134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0145  *
0146  * Alternatively, you may choose to be licensed under the terms of the
0147  * GNU General Public License ("GPL") version 2 as published by the Free
0148  * Software Foundation.
0149  *
0150  *****************************************************************************/
0151 
0152 #include "acpi.h"
0153 #include "accommon.h"
0154 #include "acresrc.h"
0155 #include "acnamesp.h"
0156 
0157 
0158 #define _COMPONENT          ACPI_RESOURCES
0159         ACPI_MODULE_NAME    ("rscalc")
0160 
0161 
0162 /* Local prototypes */
0163 
0164 static UINT8
0165 AcpiRsCountSetBits (
0166     UINT16                  BitField);
0167 
0168 static ACPI_RS_LENGTH
0169 AcpiRsStructOptionLength (
0170     ACPI_RESOURCE_SOURCE    *ResourceSource);
0171 
0172 static UINT32
0173 AcpiRsStreamOptionLength (
0174     UINT32                  ResourceLength,
0175     UINT32                  MinimumTotalLength);
0176 
0177 
0178 /*******************************************************************************
0179  *
0180  * FUNCTION:    AcpiRsCountSetBits
0181  *
0182  * PARAMETERS:  BitField        - Field in which to count bits
0183  *
0184  * RETURN:      Number of bits set within the field
0185  *
0186  * DESCRIPTION: Count the number of bits set in a resource field. Used for
0187  *              (Short descriptor) interrupt and DMA lists.
0188  *
0189  ******************************************************************************/
0190 
0191 static UINT8
0192 AcpiRsCountSetBits (
0193     UINT16                  BitField)
0194 {
0195     UINT8                   BitsSet;
0196 
0197 
0198     ACPI_FUNCTION_ENTRY ();
0199 
0200 
0201     for (BitsSet = 0; BitField; BitsSet++)
0202     {
0203         /* Zero the least significant bit that is set */
0204 
0205         BitField &= (UINT16) (BitField - 1);
0206     }
0207 
0208     return (BitsSet);
0209 }
0210 
0211 
0212 /*******************************************************************************
0213  *
0214  * FUNCTION:    AcpiRsStructOptionLength
0215  *
0216  * PARAMETERS:  ResourceSource      - Pointer to optional descriptor field
0217  *
0218  * RETURN:      Status
0219  *
0220  * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
0221  *              ResourceSource fields in some Large descriptors. Used during
0222  *              list-to-stream conversion
0223  *
0224  ******************************************************************************/
0225 
0226 static ACPI_RS_LENGTH
0227 AcpiRsStructOptionLength (
0228     ACPI_RESOURCE_SOURCE    *ResourceSource)
0229 {
0230     ACPI_FUNCTION_ENTRY ();
0231 
0232 
0233     /*
0234      * If the ResourceSource string is valid, return the size of the string
0235      * (StringLength includes the NULL terminator) plus the size of the
0236      * ResourceSourceIndex (1).
0237      */
0238     if (ResourceSource->StringPtr)
0239     {
0240         return ((ACPI_RS_LENGTH) (ResourceSource->StringLength + 1));
0241     }
0242 
0243     return (0);
0244 }
0245 
0246 
0247 /*******************************************************************************
0248  *
0249  * FUNCTION:    AcpiRsStreamOptionLength
0250  *
0251  * PARAMETERS:  ResourceLength      - Length from the resource header
0252  *              MinimumTotalLength  - Minimum length of this resource, before
0253  *                                    any optional fields. Includes header size
0254  *
0255  * RETURN:      Length of optional string (0 if no string present)
0256  *
0257  * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
0258  *              ResourceSource fields in some Large descriptors. Used during
0259  *              stream-to-list conversion
0260  *
0261  ******************************************************************************/
0262 
0263 static UINT32
0264 AcpiRsStreamOptionLength (
0265     UINT32                  ResourceLength,
0266     UINT32                  MinimumAmlResourceLength)
0267 {
0268     UINT32                  StringLength = 0;
0269 
0270 
0271     ACPI_FUNCTION_ENTRY ();
0272 
0273 
0274     /*
0275      * The ResourceSourceIndex and ResourceSource are optional elements of
0276      * some Large-type resource descriptors.
0277      */
0278 
0279     /*
0280      * If the length of the actual resource descriptor is greater than the
0281      * ACPI spec-defined minimum length, it means that a ResourceSourceIndex
0282      * exists and is followed by a (required) null terminated string. The
0283      * string length (including the null terminator) is the resource length
0284      * minus the minimum length, minus one byte for the ResourceSourceIndex
0285      * itself.
0286      */
0287     if (ResourceLength > MinimumAmlResourceLength)
0288     {
0289         /* Compute the length of the optional string */
0290 
0291         StringLength = ResourceLength - MinimumAmlResourceLength - 1;
0292     }
0293 
0294     /*
0295      * Round the length up to a multiple of the native word in order to
0296      * guarantee that the entire resource descriptor is native word aligned
0297      */
0298     return ((UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (StringLength));
0299 }
0300 
0301 
0302 /*******************************************************************************
0303  *
0304  * FUNCTION:    AcpiRsGetAmlLength
0305  *
0306  * PARAMETERS:  Resource            - Pointer to the resource linked list
0307  *              ResourceListSize    - Size of the resource linked list
0308  *              SizeNeeded          - Where the required size is returned
0309  *
0310  * RETURN:      Status
0311  *
0312  * DESCRIPTION: Takes a linked list of internal resource descriptors and
0313  *              calculates the size buffer needed to hold the corresponding
0314  *              external resource byte stream.
0315  *
0316  ******************************************************************************/
0317 
0318 ACPI_STATUS
0319 AcpiRsGetAmlLength (
0320     ACPI_RESOURCE           *Resource,
0321     ACPI_SIZE               ResourceListSize,
0322     ACPI_SIZE               *SizeNeeded)
0323 {
0324     ACPI_SIZE               AmlSizeNeeded = 0;
0325     ACPI_RESOURCE           *ResourceEnd;
0326     ACPI_RS_LENGTH          TotalSize;
0327 
0328 
0329     ACPI_FUNCTION_TRACE (RsGetAmlLength);
0330 
0331 
0332     /* Traverse entire list of internal resource descriptors */
0333 
0334     ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, ResourceListSize);
0335     while (Resource < ResourceEnd)
0336     {
0337         /* Validate the descriptor type */
0338 
0339         if (Resource->Type > ACPI_RESOURCE_TYPE_MAX)
0340         {
0341             return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
0342         }
0343 
0344         /* Sanity check the length. It must not be zero, or we loop forever */
0345 
0346         if (!Resource->Length)
0347         {
0348             return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
0349         }
0350 
0351         /* Get the base size of the (external stream) resource descriptor */
0352 
0353         TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type];
0354 
0355         /*
0356          * Augment the base size for descriptors with optional and/or
0357          * variable-length fields
0358          */
0359         switch (Resource->Type)
0360         {
0361         case ACPI_RESOURCE_TYPE_IRQ:
0362 
0363             /* Length can be 3 or 2 */
0364 
0365             if (Resource->Data.Irq.DescriptorLength == 2)
0366             {
0367                 TotalSize--;
0368             }
0369             break;
0370 
0371 
0372         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
0373 
0374             /* Length can be 1 or 0 */
0375 
0376             if (Resource->Data.Irq.DescriptorLength == 0)
0377             {
0378                 TotalSize--;
0379             }
0380             break;
0381 
0382 
0383         case ACPI_RESOURCE_TYPE_VENDOR:
0384             /*
0385              * Vendor Defined Resource:
0386              * For a Vendor Specific resource, if the Length is between 1 and 7
0387              * it will be created as a Small Resource data type, otherwise it
0388              * is a Large Resource data type.
0389              */
0390             if (Resource->Data.Vendor.ByteLength > 7)
0391             {
0392                 /* Base size of a Large resource descriptor */
0393 
0394                 TotalSize = sizeof (AML_RESOURCE_LARGE_HEADER);
0395             }
0396 
0397             /* Add the size of the vendor-specific data */
0398 
0399             TotalSize = (ACPI_RS_LENGTH)
0400                 (TotalSize + Resource->Data.Vendor.ByteLength);
0401             break;
0402 
0403 
0404         case ACPI_RESOURCE_TYPE_END_TAG:
0405             /*
0406              * End Tag:
0407              * We are done -- return the accumulated total size.
0408              */
0409             *SizeNeeded = AmlSizeNeeded + TotalSize;
0410 
0411             /* Normal exit */
0412 
0413             return_ACPI_STATUS (AE_OK);
0414 
0415 
0416         case ACPI_RESOURCE_TYPE_ADDRESS16:
0417             /*
0418              * 16-Bit Address Resource:
0419              * Add the size of the optional ResourceSource info
0420              */
0421             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0422                 AcpiRsStructOptionLength (
0423                     &Resource->Data.Address16.ResourceSource));
0424             break;
0425 
0426 
0427         case ACPI_RESOURCE_TYPE_ADDRESS32:
0428             /*
0429              * 32-Bit Address Resource:
0430              * Add the size of the optional ResourceSource info
0431              */
0432             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0433                 AcpiRsStructOptionLength (
0434                     &Resource->Data.Address32.ResourceSource));
0435             break;
0436 
0437 
0438         case ACPI_RESOURCE_TYPE_ADDRESS64:
0439             /*
0440              * 64-Bit Address Resource:
0441              * Add the size of the optional ResourceSource info
0442              */
0443             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0444                 AcpiRsStructOptionLength (
0445                     &Resource->Data.Address64.ResourceSource));
0446             break;
0447 
0448 
0449         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
0450             /*
0451              * Extended IRQ Resource:
0452              * Add the size of each additional optional interrupt beyond the
0453              * required 1 (4 bytes for each UINT32 interrupt number)
0454              */
0455             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0456                 ((Resource->Data.ExtendedIrq.InterruptCount - 1) * 4) +
0457 
0458                 /* Add the size of the optional ResourceSource info */
0459 
0460                 AcpiRsStructOptionLength (
0461                     &Resource->Data.ExtendedIrq.ResourceSource));
0462             break;
0463 
0464 
0465         case ACPI_RESOURCE_TYPE_GPIO:
0466 
0467             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0468                 (Resource->Data.Gpio.PinTableLength * 2) +
0469                 Resource->Data.Gpio.ResourceSource.StringLength +
0470                 Resource->Data.Gpio.VendorLength);
0471 
0472             break;
0473 
0474         case ACPI_RESOURCE_TYPE_PIN_FUNCTION:
0475 
0476             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0477                 (Resource->Data.PinFunction.PinTableLength * 2) +
0478                 Resource->Data.PinFunction.ResourceSource.StringLength +
0479                 Resource->Data.PinFunction.VendorLength);
0480 
0481             break;
0482 
0483         case ACPI_RESOURCE_TYPE_CLOCK_INPUT:
0484 
0485             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0486                 Resource->Data.ClockInput.ResourceSource.StringLength);
0487 
0488             break;
0489 
0490 
0491         case ACPI_RESOURCE_TYPE_SERIAL_BUS:
0492 
0493             TotalSize = AcpiGbl_AmlResourceSerialBusSizes [
0494                 Resource->Data.CommonSerialBus.Type];
0495 
0496             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0497                 Resource->Data.I2cSerialBus.ResourceSource.StringLength +
0498                 Resource->Data.I2cSerialBus.VendorLength);
0499 
0500             break;
0501 
0502         case ACPI_RESOURCE_TYPE_PIN_CONFIG:
0503 
0504             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0505                 (Resource->Data.PinConfig.PinTableLength * 2) +
0506                 Resource->Data.PinConfig.ResourceSource.StringLength +
0507                 Resource->Data.PinConfig.VendorLength);
0508 
0509             break;
0510 
0511         case ACPI_RESOURCE_TYPE_PIN_GROUP:
0512 
0513             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0514                 (Resource->Data.PinGroup.PinTableLength * 2) +
0515                 Resource->Data.PinGroup.ResourceLabel.StringLength +
0516                 Resource->Data.PinGroup.VendorLength);
0517 
0518             break;
0519 
0520         case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION:
0521 
0522             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0523                 Resource->Data.PinGroupFunction.ResourceSource.StringLength +
0524                 Resource->Data.PinGroupFunction.ResourceSourceLabel.StringLength +
0525                 Resource->Data.PinGroupFunction.VendorLength);
0526 
0527             break;
0528 
0529         case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG:
0530 
0531             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
0532                 Resource->Data.PinGroupConfig.ResourceSource.StringLength +
0533                 Resource->Data.PinGroupConfig.ResourceSourceLabel.StringLength +
0534                 Resource->Data.PinGroupConfig.VendorLength);
0535 
0536             break;
0537 
0538         default:
0539 
0540             break;
0541         }
0542 
0543         /* Update the total */
0544 
0545         AmlSizeNeeded += TotalSize;
0546 
0547         /* Point to the next object */
0548 
0549         Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length);
0550     }
0551 
0552     /* Did not find an EndTag resource descriptor */
0553 
0554     return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
0555 }
0556 
0557 
0558 /*******************************************************************************
0559  *
0560  * FUNCTION:    AcpiRsGetListLength
0561  *
0562  * PARAMETERS:  AmlBuffer           - Pointer to the resource byte stream
0563  *              AmlBufferLength     - Size of AmlBuffer
0564  *              SizeNeeded          - Where the size needed is returned
0565  *
0566  * RETURN:      Status
0567  *
0568  * DESCRIPTION: Takes an external resource byte stream and calculates the size
0569  *              buffer needed to hold the corresponding internal resource
0570  *              descriptor linked list.
0571  *
0572  ******************************************************************************/
0573 
0574 ACPI_STATUS
0575 AcpiRsGetListLength (
0576     UINT8                   *AmlBuffer,
0577     UINT32                  AmlBufferLength,
0578     ACPI_SIZE               *SizeNeeded)
0579 {
0580     ACPI_STATUS             Status;
0581     UINT8                   *EndAml;
0582     UINT8                   *Buffer;
0583     UINT32                  BufferSize;
0584     UINT16                  Temp16;
0585     UINT16                  ResourceLength;
0586     UINT32                  ExtraStructBytes;
0587     UINT8                   ResourceIndex;
0588     UINT8                   MinimumAmlResourceLength;
0589     AML_RESOURCE            *AmlResource;
0590 
0591 
0592     ACPI_FUNCTION_TRACE (RsGetListLength);
0593 
0594 
0595     *SizeNeeded = ACPI_RS_SIZE_MIN;         /* Minimum size is one EndTag */
0596     EndAml = AmlBuffer + AmlBufferLength;
0597 
0598     /* Walk the list of AML resource descriptors */
0599 
0600     while (AmlBuffer < EndAml)
0601     {
0602         /* Validate the Resource Type and Resource Length */
0603 
0604         Status = AcpiUtValidateResource (NULL, AmlBuffer, &ResourceIndex);
0605         if (ACPI_FAILURE (Status))
0606         {
0607             /*
0608              * Exit on failure. Cannot continue because the descriptor length
0609              * may be bogus also.
0610              */
0611             return_ACPI_STATUS (Status);
0612         }
0613 
0614         AmlResource = (void *) AmlBuffer;
0615 
0616         /* Get the resource length and base (minimum) AML size */
0617 
0618         ResourceLength = AcpiUtGetResourceLength (AmlBuffer);
0619         MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
0620 
0621         /*
0622          * Augment the size for descriptors with optional
0623          * and/or variable length fields
0624          */
0625         ExtraStructBytes = 0;
0626         Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer);
0627 
0628         switch (AcpiUtGetResourceType (AmlBuffer))
0629         {
0630         case ACPI_RESOURCE_NAME_IRQ:
0631             /*
0632              * IRQ Resource:
0633              * Get the number of bits set in the 16-bit IRQ mask
0634              */
0635             ACPI_MOVE_16_TO_16 (&Temp16, Buffer);
0636             ExtraStructBytes = AcpiRsCountSetBits (Temp16);
0637             break;
0638 
0639 
0640         case ACPI_RESOURCE_NAME_DMA:
0641             /*
0642              * DMA Resource:
0643              * Get the number of bits set in the 8-bit DMA mask
0644              */
0645             ExtraStructBytes = AcpiRsCountSetBits (*Buffer);
0646             break;
0647 
0648 
0649         case ACPI_RESOURCE_NAME_VENDOR_SMALL:
0650         case ACPI_RESOURCE_NAME_VENDOR_LARGE:
0651             /*
0652              * Vendor Resource:
0653              * Get the number of vendor data bytes
0654              */
0655             ExtraStructBytes = ResourceLength;
0656 
0657             /*
0658              * There is already one byte included in the minimum
0659              * descriptor size. If there are extra struct bytes,
0660              * subtract one from the count.
0661              */
0662             if (ExtraStructBytes)
0663             {
0664                 ExtraStructBytes--;
0665             }
0666             break;
0667 
0668 
0669         case ACPI_RESOURCE_NAME_END_TAG:
0670             /*
0671              * End Tag: This is the normal exit
0672              */
0673             return_ACPI_STATUS (AE_OK);
0674 
0675 
0676         case ACPI_RESOURCE_NAME_ADDRESS32:
0677         case ACPI_RESOURCE_NAME_ADDRESS16:
0678         case ACPI_RESOURCE_NAME_ADDRESS64:
0679             /*
0680              * Address Resource:
0681              * Add the size of the optional ResourceSource
0682              */
0683             ExtraStructBytes = AcpiRsStreamOptionLength (
0684                 ResourceLength, MinimumAmlResourceLength);
0685             break;
0686 
0687 
0688         case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
0689             /*
0690              * Extended IRQ Resource:
0691              * Using the InterruptTableLength, add 4 bytes for each additional
0692              * interrupt. Note: at least one interrupt is required and is
0693              * included in the minimum descriptor size (reason for the -1)
0694              */
0695             ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32);
0696 
0697             /* Add the size of the optional ResourceSource */
0698 
0699             ExtraStructBytes += AcpiRsStreamOptionLength (
0700                 ResourceLength - ExtraStructBytes, MinimumAmlResourceLength);
0701             break;
0702 
0703         case ACPI_RESOURCE_NAME_GPIO:
0704 
0705             /* Vendor data is optional */
0706 
0707             if (AmlResource->Gpio.VendorLength)
0708             {
0709                 ExtraStructBytes +=
0710                     AmlResource->Gpio.VendorOffset -
0711                     AmlResource->Gpio.PinTableOffset +
0712                     AmlResource->Gpio.VendorLength;
0713             }
0714             else
0715             {
0716                 ExtraStructBytes +=
0717                     AmlResource->LargeHeader.ResourceLength +
0718                     sizeof (AML_RESOURCE_LARGE_HEADER) -
0719                     AmlResource->Gpio.PinTableOffset;
0720             }
0721             break;
0722 
0723         case ACPI_RESOURCE_NAME_PIN_FUNCTION:
0724 
0725             /* Vendor data is optional */
0726 
0727             if (AmlResource->PinFunction.VendorLength)
0728             {
0729                 ExtraStructBytes +=
0730                     AmlResource->PinFunction.VendorOffset -
0731                     AmlResource->PinFunction.PinTableOffset +
0732                     AmlResource->PinFunction.VendorLength;
0733             }
0734             else
0735             {
0736                 ExtraStructBytes +=
0737                     AmlResource->LargeHeader.ResourceLength +
0738                     sizeof (AML_RESOURCE_LARGE_HEADER) -
0739                     AmlResource->PinFunction.PinTableOffset;
0740             }
0741             break;
0742 
0743         case ACPI_RESOURCE_NAME_SERIAL_BUS: {
0744             /* Avoid undefined behavior: member access within misaligned address */
0745 
0746             AML_RESOURCE_COMMON_SERIALBUS CommonSerialBus;
0747             memcpy(&CommonSerialBus, AmlResource, sizeof(CommonSerialBus));
0748 
0749             MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[
0750                 CommonSerialBus.Type];
0751             ExtraStructBytes +=
0752                 CommonSerialBus.ResourceLength -
0753                 MinimumAmlResourceLength;
0754             break;
0755         }
0756 
0757         case ACPI_RESOURCE_NAME_PIN_CONFIG:
0758 
0759             /* Vendor data is optional */
0760 
0761             if (AmlResource->PinConfig.VendorLength)
0762             {
0763                 ExtraStructBytes +=
0764                     AmlResource->PinConfig.VendorOffset -
0765                     AmlResource->PinConfig.PinTableOffset +
0766                     AmlResource->PinConfig.VendorLength;
0767             }
0768             else
0769             {
0770                 ExtraStructBytes +=
0771                     AmlResource->LargeHeader.ResourceLength +
0772                     sizeof (AML_RESOURCE_LARGE_HEADER) -
0773                     AmlResource->PinConfig.PinTableOffset;
0774             }
0775             break;
0776 
0777         case ACPI_RESOURCE_NAME_PIN_GROUP:
0778 
0779             ExtraStructBytes +=
0780                 AmlResource->PinGroup.VendorOffset -
0781                 AmlResource->PinGroup.PinTableOffset +
0782                 AmlResource->PinGroup.VendorLength;
0783 
0784             break;
0785 
0786         case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION:
0787 
0788             ExtraStructBytes +=
0789                 AmlResource->PinGroupFunction.VendorOffset -
0790                 AmlResource->PinGroupFunction.ResSourceOffset +
0791                 AmlResource->PinGroupFunction.VendorLength;
0792 
0793             break;
0794 
0795         case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG:
0796 
0797             ExtraStructBytes +=
0798                 AmlResource->PinGroupConfig.VendorOffset -
0799                 AmlResource->PinGroupConfig.ResSourceOffset +
0800                 AmlResource->PinGroupConfig.VendorLength;
0801 
0802             break;
0803 
0804         case ACPI_RESOURCE_NAME_CLOCK_INPUT:
0805             ExtraStructBytes = AcpiRsStreamOptionLength (
0806                 ResourceLength, MinimumAmlResourceLength);
0807 
0808             break;
0809 
0810         default:
0811 
0812             break;
0813         }
0814 
0815         /*
0816          * Update the required buffer size for the internal descriptor structs
0817          *
0818          * Important: Round the size up for the appropriate alignment. This
0819          * is a requirement on IA64.
0820          */
0821         if (AcpiUtGetResourceType (AmlBuffer) ==
0822             ACPI_RESOURCE_NAME_SERIAL_BUS)
0823         {
0824             /* Avoid undefined behavior: member access within misaligned address */
0825 
0826             AML_RESOURCE_COMMON_SERIALBUS CommonSerialBus;
0827             memcpy(&CommonSerialBus, AmlResource, sizeof(CommonSerialBus));
0828 
0829             BufferSize = AcpiGbl_ResourceStructSerialBusSizes[
0830                 CommonSerialBus.Type] + ExtraStructBytes;
0831         }
0832         else
0833         {
0834             BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] +
0835                 ExtraStructBytes;
0836         }
0837 
0838         BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize);
0839         *SizeNeeded += BufferSize;
0840 
0841         ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES,
0842             "Type %.2X, AmlLength %.2X InternalLength %.2X%8X\n",
0843             AcpiUtGetResourceType (AmlBuffer),
0844             AcpiUtGetDescriptorLength (AmlBuffer), ACPI_FORMAT_UINT64(*SizeNeeded)));
0845 
0846         /*
0847          * Point to the next resource within the AML stream using the length
0848          * contained in the resource descriptor header
0849          */
0850         AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer);
0851     }
0852 
0853     /* Did not find an EndTag resource descriptor */
0854 
0855     return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
0856 }
0857 
0858 
0859 /*******************************************************************************
0860  *
0861  * FUNCTION:    AcpiRsGetPciRoutingTableLength
0862  *
0863  * PARAMETERS:  PackageObject           - Pointer to the package object
0864  *              BufferSizeNeeded        - UINT32 pointer of the size buffer
0865  *                                        needed to properly return the
0866  *                                        parsed data
0867  *
0868  * RETURN:      Status
0869  *
0870  * DESCRIPTION: Given a package representing a PCI routing table, this
0871  *              calculates the size of the corresponding linked list of
0872  *              descriptions.
0873  *
0874  ******************************************************************************/
0875 
0876 ACPI_STATUS
0877 AcpiRsGetPciRoutingTableLength (
0878     ACPI_OPERAND_OBJECT     *PackageObject,
0879     ACPI_SIZE               *BufferSizeNeeded)
0880 {
0881     UINT32                  NumberOfElements;
0882     ACPI_SIZE               TempSizeNeeded = 0;
0883     ACPI_OPERAND_OBJECT     **TopObjectList;
0884     UINT32                  Index;
0885     ACPI_OPERAND_OBJECT     *PackageElement;
0886     ACPI_OPERAND_OBJECT     **SubObjectList;
0887     BOOLEAN                 NameFound;
0888     UINT32                  TableIndex;
0889 
0890 
0891     ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength);
0892 
0893 
0894     NumberOfElements = PackageObject->Package.Count;
0895 
0896     /*
0897      * Calculate the size of the return buffer.
0898      * The base size is the number of elements * the sizes of the
0899      * structures. Additional space for the strings is added below.
0900      * The minus one is to subtract the size of the UINT8 Source[1]
0901      * member because it is added below.
0902      *
0903      * But each PRT_ENTRY structure has a pointer to a string and
0904      * the size of that string must be found.
0905      */
0906     TopObjectList = PackageObject->Package.Elements;
0907 
0908     for (Index = 0; Index < NumberOfElements; Index++)
0909     {
0910         /* Dereference the subpackage */
0911 
0912         PackageElement = *TopObjectList;
0913 
0914         /* We must have a valid Package object */
0915 
0916         if (!PackageElement ||
0917             (PackageElement->Common.Type != ACPI_TYPE_PACKAGE))
0918         {
0919             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
0920         }
0921 
0922         /*
0923          * The SubObjectList will now point to an array of the
0924          * four IRQ elements: Address, Pin, Source and SourceIndex
0925          */
0926         SubObjectList = PackageElement->Package.Elements;
0927 
0928         /* Scan the IrqTableElements for the Source Name String */
0929 
0930         NameFound = FALSE;
0931 
0932         for (TableIndex = 0;
0933              TableIndex < PackageElement->Package.Count && !NameFound;
0934              TableIndex++)
0935         {
0936             if (*SubObjectList && /* Null object allowed */
0937 
0938                 ((ACPI_TYPE_STRING ==
0939                     (*SubObjectList)->Common.Type) ||
0940 
0941                 ((ACPI_TYPE_LOCAL_REFERENCE ==
0942                     (*SubObjectList)->Common.Type) &&
0943 
0944                     ((*SubObjectList)->Reference.Class ==
0945                         ACPI_REFCLASS_NAME))))
0946             {
0947                 NameFound = TRUE;
0948             }
0949             else
0950             {
0951                 /* Look at the next element */
0952 
0953                 SubObjectList++;
0954             }
0955         }
0956 
0957         TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);
0958 
0959         /* Was a String type found? */
0960 
0961         if (NameFound)
0962         {
0963             if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING)
0964             {
0965                 /*
0966                  * The length String.Length field does not include the
0967                  * terminating NULL, add 1
0968                  */
0969                 TempSizeNeeded += ((ACPI_SIZE)
0970                     (*SubObjectList)->String.Length + 1);
0971             }
0972             else
0973             {
0974                 TempSizeNeeded += AcpiNsGetPathnameLength (
0975                     (*SubObjectList)->Reference.Node);
0976             }
0977         }
0978         else
0979         {
0980             /*
0981              * If no name was found, then this is a NULL, which is
0982              * translated as a UINT32 zero.
0983              */
0984             TempSizeNeeded += sizeof (UINT32);
0985         }
0986 
0987         /* Round up the size since each element must be aligned */
0988 
0989         TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded);
0990 
0991         /* Point to the next ACPI_OPERAND_OBJECT */
0992 
0993         TopObjectList++;
0994     }
0995 
0996     /*
0997      * Add an extra element to the end of the list, essentially a
0998      * NULL terminator
0999      */
1000     *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE);
1001     return_ACPI_STATUS (AE_OK);
1002 }