1 /*******************************************************************************
   2  *
   3  * Module Name: rscalc - Calculate stream and list lengths
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 #define __RSCALC_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acresrc.h"
  49 #include "acnamesp.h"
  50 
  51 
  52 #define _COMPONENT          ACPI_RESOURCES
  53         ACPI_MODULE_NAME    ("rscalc")
  54 
  55 
  56 /* Local prototypes */
  57 
  58 static UINT8
  59 AcpiRsCountSetBits (
  60     UINT16                  BitField);
  61 
  62 static ACPI_RS_LENGTH
  63 AcpiRsStructOptionLength (
  64     ACPI_RESOURCE_SOURCE    *ResourceSource);
  65 
  66 static UINT32
  67 AcpiRsStreamOptionLength (
  68     UINT32                  ResourceLength,
  69     UINT32                  MinimumTotalLength);
  70 
  71 
  72 /*******************************************************************************
  73  *
  74  * FUNCTION:    AcpiRsCountSetBits
  75  *
  76  * PARAMETERS:  BitField        - Field in which to count bits
  77  *
  78  * RETURN:      Number of bits set within the field
  79  *
  80  * DESCRIPTION: Count the number of bits set in a resource field. Used for
  81  *              (Short descriptor) interrupt and DMA lists.
  82  *
  83  ******************************************************************************/
  84 
  85 static UINT8
  86 AcpiRsCountSetBits (
  87     UINT16                  BitField)
  88 {
  89     UINT8                   BitsSet;
  90 
  91 
  92     ACPI_FUNCTION_ENTRY ();
  93 
  94 
  95     for (BitsSet = 0; BitField; BitsSet++)
  96     {
  97         /* Zero the least significant bit that is set */
  98 
  99         BitField &= (UINT16) (BitField - 1);
 100     }
 101 
 102     return (BitsSet);
 103 }
 104 
 105 
 106 /*******************************************************************************
 107  *
 108  * FUNCTION:    AcpiRsStructOptionLength
 109  *
 110  * PARAMETERS:  ResourceSource      - Pointer to optional descriptor field
 111  *
 112  * RETURN:      Status
 113  *
 114  * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
 115  *              ResourceSource fields in some Large descriptors. Used during
 116  *              list-to-stream conversion
 117  *
 118  ******************************************************************************/
 119 
 120 static ACPI_RS_LENGTH
 121 AcpiRsStructOptionLength (
 122     ACPI_RESOURCE_SOURCE    *ResourceSource)
 123 {
 124     ACPI_FUNCTION_ENTRY ();
 125 
 126 
 127     /*
 128      * If the ResourceSource string is valid, return the size of the string
 129      * (StringLength includes the NULL terminator) plus the size of the
 130      * ResourceSourceIndex (1).
 131      */
 132     if (ResourceSource->StringPtr)
 133     {
 134         return ((ACPI_RS_LENGTH) (ResourceSource->StringLength + 1));
 135     }
 136 
 137     return (0);
 138 }
 139 
 140 
 141 /*******************************************************************************
 142  *
 143  * FUNCTION:    AcpiRsStreamOptionLength
 144  *
 145  * PARAMETERS:  ResourceLength      - Length from the resource header
 146  *              MinimumTotalLength  - Minimum length of this resource, before
 147  *                                    any optional fields. Includes header size
 148  *
 149  * RETURN:      Length of optional string (0 if no string present)
 150  *
 151  * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
 152  *              ResourceSource fields in some Large descriptors. Used during
 153  *              stream-to-list conversion
 154  *
 155  ******************************************************************************/
 156 
 157 static UINT32
 158 AcpiRsStreamOptionLength (
 159     UINT32                  ResourceLength,
 160     UINT32                  MinimumAmlResourceLength)
 161 {
 162     UINT32                  StringLength = 0;
 163 
 164 
 165     ACPI_FUNCTION_ENTRY ();
 166 
 167 
 168     /*
 169      * The ResourceSourceIndex and ResourceSource are optional elements of some
 170      * Large-type resource descriptors.
 171      */
 172 
 173     /*
 174      * If the length of the actual resource descriptor is greater than the ACPI
 175      * spec-defined minimum length, it means that a ResourceSourceIndex exists
 176      * and is followed by a (required) null terminated string. The string length
 177      * (including the null terminator) is the resource length minus the minimum
 178      * length, minus one byte for the ResourceSourceIndex itself.
 179      */
 180     if (ResourceLength > MinimumAmlResourceLength)
 181     {
 182         /* Compute the length of the optional string */
 183 
 184         StringLength = ResourceLength - MinimumAmlResourceLength - 1;
 185     }
 186 
 187     /*
 188      * Round the length up to a multiple of the native word in order to
 189      * guarantee that the entire resource descriptor is native word aligned
 190      */
 191     return ((UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (StringLength));
 192 }
 193 
 194 
 195 /*******************************************************************************
 196  *
 197  * FUNCTION:    AcpiRsGetAmlLength
 198  *
 199  * PARAMETERS:  Resource            - Pointer to the resource linked list
 200  *              ResourceListSize    - Size of the resource linked list
 201  *              SizeNeeded          - Where the required size is returned
 202  *
 203  * RETURN:      Status
 204  *
 205  * DESCRIPTION: Takes a linked list of internal resource descriptors and
 206  *              calculates the size buffer needed to hold the corresponding
 207  *              external resource byte stream.
 208  *
 209  ******************************************************************************/
 210 
 211 ACPI_STATUS
 212 AcpiRsGetAmlLength (
 213     ACPI_RESOURCE           *Resource,
 214     ACPI_SIZE               ResourceListSize,
 215     ACPI_SIZE               *SizeNeeded)
 216 {
 217     ACPI_SIZE               AmlSizeNeeded = 0;
 218     ACPI_RESOURCE           *ResourceEnd;
 219     ACPI_RS_LENGTH          TotalSize;
 220 
 221 
 222     ACPI_FUNCTION_TRACE (RsGetAmlLength);
 223 
 224 
 225     /* Traverse entire list of internal resource descriptors */
 226 
 227     ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, ResourceListSize);
 228     while (Resource < ResourceEnd)
 229     {
 230         /* Validate the descriptor type */
 231 
 232         if (Resource->Type > ACPI_RESOURCE_TYPE_MAX)
 233         {
 234             return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
 235         }
 236 
 237         /* Sanity check the length. It must not be zero, or we loop forever */
 238 
 239         if (!Resource->Length)
 240         {
 241             return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
 242         }
 243 
 244         /* Get the base size of the (external stream) resource descriptor */
 245 
 246         TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type];
 247 
 248         /*
 249          * Augment the base size for descriptors with optional and/or
 250          * variable-length fields
 251          */
 252         switch (Resource->Type)
 253         {
 254         case ACPI_RESOURCE_TYPE_IRQ:
 255 
 256             /* Length can be 3 or 2 */
 257 
 258             if (Resource->Data.Irq.DescriptorLength == 2)
 259             {
 260                 TotalSize--;
 261             }
 262             break;
 263 
 264 
 265         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 266 
 267             /* Length can be 1 or 0 */
 268 
 269             if (Resource->Data.Irq.DescriptorLength == 0)
 270             {
 271                 TotalSize--;
 272             }
 273             break;
 274 
 275 
 276         case ACPI_RESOURCE_TYPE_VENDOR:
 277             /*
 278              * Vendor Defined Resource:
 279              * For a Vendor Specific resource, if the Length is between 1 and 7
 280              * it will be created as a Small Resource data type, otherwise it
 281              * is a Large Resource data type.
 282              */
 283             if (Resource->Data.Vendor.ByteLength > 7)
 284             {
 285                 /* Base size of a Large resource descriptor */
 286 
 287                 TotalSize = sizeof (AML_RESOURCE_LARGE_HEADER);
 288             }
 289 
 290             /* Add the size of the vendor-specific data */
 291 
 292             TotalSize = (ACPI_RS_LENGTH)
 293                 (TotalSize + Resource->Data.Vendor.ByteLength);
 294             break;
 295 
 296 
 297         case ACPI_RESOURCE_TYPE_END_TAG:
 298             /*
 299              * End Tag:
 300              * We are done -- return the accumulated total size.
 301              */
 302             *SizeNeeded = AmlSizeNeeded + TotalSize;
 303 
 304             /* Normal exit */
 305 
 306             return_ACPI_STATUS (AE_OK);
 307 
 308 
 309         case ACPI_RESOURCE_TYPE_ADDRESS16:
 310             /*
 311              * 16-Bit Address Resource:
 312              * Add the size of the optional ResourceSource info
 313              */
 314             TotalSize = (ACPI_RS_LENGTH)
 315                 (TotalSize + AcpiRsStructOptionLength (
 316                                 &Resource->Data.Address16.ResourceSource));
 317             break;
 318 
 319 
 320         case ACPI_RESOURCE_TYPE_ADDRESS32:
 321             /*
 322              * 32-Bit Address Resource:
 323              * Add the size of the optional ResourceSource info
 324              */
 325             TotalSize = (ACPI_RS_LENGTH)
 326                 (TotalSize + AcpiRsStructOptionLength (
 327                                 &Resource->Data.Address32.ResourceSource));
 328             break;
 329 
 330 
 331         case ACPI_RESOURCE_TYPE_ADDRESS64:
 332             /*
 333              * 64-Bit Address Resource:
 334              * Add the size of the optional ResourceSource info
 335              */
 336             TotalSize = (ACPI_RS_LENGTH)
 337                 (TotalSize + AcpiRsStructOptionLength (
 338                                 &Resource->Data.Address64.ResourceSource));
 339             break;
 340 
 341 
 342         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 343             /*
 344              * Extended IRQ Resource:
 345              * Add the size of each additional optional interrupt beyond the
 346              * required 1 (4 bytes for each UINT32 interrupt number)
 347              */
 348             TotalSize = (ACPI_RS_LENGTH)
 349                 (TotalSize +
 350                 ((Resource->Data.ExtendedIrq.InterruptCount - 1) * 4) +
 351 
 352                 /* Add the size of the optional ResourceSource info */
 353 
 354                 AcpiRsStructOptionLength (
 355                     &Resource->Data.ExtendedIrq.ResourceSource));
 356             break;
 357 
 358 
 359         case ACPI_RESOURCE_TYPE_GPIO:
 360 
 361             TotalSize = (ACPI_RS_LENGTH) (TotalSize + (Resource->Data.Gpio.PinTableLength * 2) +
 362                 Resource->Data.Gpio.ResourceSource.StringLength +
 363                 Resource->Data.Gpio.VendorLength);
 364 
 365             break;
 366 
 367 
 368         case ACPI_RESOURCE_TYPE_SERIAL_BUS:
 369 
 370             TotalSize = AcpiGbl_AmlResourceSerialBusSizes [Resource->Data.CommonSerialBus.Type];
 371 
 372             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
 373                 Resource->Data.I2cSerialBus.ResourceSource.StringLength +
 374                 Resource->Data.I2cSerialBus.VendorLength);
 375 
 376             break;
 377 
 378         default:
 379 
 380             break;
 381         }
 382 
 383         /* Update the total */
 384 
 385         AmlSizeNeeded += TotalSize;
 386 
 387         /* Point to the next object */
 388 
 389         Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length);
 390     }
 391 
 392     /* Did not find an EndTag resource descriptor */
 393 
 394     return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
 395 }
 396 
 397 
 398 /*******************************************************************************
 399  *
 400  * FUNCTION:    AcpiRsGetListLength
 401  *
 402  * PARAMETERS:  AmlBuffer           - Pointer to the resource byte stream
 403  *              AmlBufferLength     - Size of AmlBuffer
 404  *              SizeNeeded          - Where the size needed is returned
 405  *
 406  * RETURN:      Status
 407  *
 408  * DESCRIPTION: Takes an external resource byte stream and calculates the size
 409  *              buffer needed to hold the corresponding internal resource
 410  *              descriptor linked list.
 411  *
 412  ******************************************************************************/
 413 
 414 ACPI_STATUS
 415 AcpiRsGetListLength (
 416     UINT8                   *AmlBuffer,
 417     UINT32                  AmlBufferLength,
 418     ACPI_SIZE               *SizeNeeded)
 419 {
 420     ACPI_STATUS             Status;
 421     UINT8                   *EndAml;
 422     UINT8                   *Buffer;
 423     UINT32                  BufferSize;
 424     UINT16                  Temp16;
 425     UINT16                  ResourceLength;
 426     UINT32                  ExtraStructBytes;
 427     UINT8                   ResourceIndex;
 428     UINT8                   MinimumAmlResourceLength;
 429     AML_RESOURCE            *AmlResource;
 430 
 431 
 432     ACPI_FUNCTION_TRACE (RsGetListLength);
 433 
 434 
 435     *SizeNeeded = ACPI_RS_SIZE_MIN;         /* Minimum size is one EndTag */
 436     EndAml = AmlBuffer + AmlBufferLength;
 437 
 438     /* Walk the list of AML resource descriptors */
 439 
 440     while (AmlBuffer < EndAml)
 441     {
 442         /* Validate the Resource Type and Resource Length */
 443 
 444         Status = AcpiUtValidateResource (NULL, AmlBuffer, &ResourceIndex);
 445         if (ACPI_FAILURE (Status))
 446         {
 447             /*
 448              * Exit on failure. Cannot continue because the descriptor length
 449              * may be bogus also.
 450              */
 451             return_ACPI_STATUS (Status);
 452         }
 453 
 454         AmlResource = (void *) AmlBuffer;
 455 
 456         /* Get the resource length and base (minimum) AML size */
 457 
 458         ResourceLength = AcpiUtGetResourceLength (AmlBuffer);
 459         MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
 460 
 461         /*
 462          * Augment the size for descriptors with optional
 463          * and/or variable length fields
 464          */
 465         ExtraStructBytes = 0;
 466         Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer);
 467 
 468         switch (AcpiUtGetResourceType (AmlBuffer))
 469         {
 470         case ACPI_RESOURCE_NAME_IRQ:
 471             /*
 472              * IRQ Resource:
 473              * Get the number of bits set in the 16-bit IRQ mask
 474              */
 475             ACPI_MOVE_16_TO_16 (&Temp16, Buffer);
 476             ExtraStructBytes = AcpiRsCountSetBits (Temp16);
 477             break;
 478 
 479 
 480         case ACPI_RESOURCE_NAME_DMA:
 481             /*
 482              * DMA Resource:
 483              * Get the number of bits set in the 8-bit DMA mask
 484              */
 485             ExtraStructBytes = AcpiRsCountSetBits (*Buffer);
 486             break;
 487 
 488 
 489         case ACPI_RESOURCE_NAME_VENDOR_SMALL:
 490         case ACPI_RESOURCE_NAME_VENDOR_LARGE:
 491             /*
 492              * Vendor Resource:
 493              * Get the number of vendor data bytes
 494              */
 495             ExtraStructBytes = ResourceLength;
 496 
 497             /*
 498              * There is already one byte included in the minimum
 499              * descriptor size. If there are extra struct bytes,
 500              * subtract one from the count.
 501              */
 502             if (ExtraStructBytes)
 503             {
 504                 ExtraStructBytes--;
 505             }
 506             break;
 507 
 508 
 509         case ACPI_RESOURCE_NAME_END_TAG:
 510             /*
 511              * End Tag: This is the normal exit
 512              */
 513             return_ACPI_STATUS (AE_OK);
 514 
 515 
 516         case ACPI_RESOURCE_NAME_ADDRESS32:
 517         case ACPI_RESOURCE_NAME_ADDRESS16:
 518         case ACPI_RESOURCE_NAME_ADDRESS64:
 519             /*
 520              * Address Resource:
 521              * Add the size of the optional ResourceSource
 522              */
 523             ExtraStructBytes = AcpiRsStreamOptionLength (
 524                 ResourceLength, MinimumAmlResourceLength);
 525             break;
 526 
 527 
 528         case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
 529             /*
 530              * Extended IRQ Resource:
 531              * Using the InterruptTableLength, add 4 bytes for each additional
 532              * interrupt. Note: at least one interrupt is required and is
 533              * included in the minimum descriptor size (reason for the -1)
 534              */
 535             ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32);
 536 
 537             /* Add the size of the optional ResourceSource */
 538 
 539             ExtraStructBytes += AcpiRsStreamOptionLength (
 540                 ResourceLength - ExtraStructBytes, MinimumAmlResourceLength);
 541             break;
 542 
 543         case ACPI_RESOURCE_NAME_GPIO:
 544 
 545             /* Vendor data is optional */
 546 
 547             if (AmlResource->Gpio.VendorLength)
 548             {
 549                 ExtraStructBytes += AmlResource->Gpio.VendorOffset -
 550                     AmlResource->Gpio.PinTableOffset + AmlResource->Gpio.VendorLength;
 551             }
 552             else
 553             {
 554                 ExtraStructBytes += AmlResource->LargeHeader.ResourceLength +
 555                     sizeof (AML_RESOURCE_LARGE_HEADER) -
 556                     AmlResource->Gpio.PinTableOffset;
 557             }
 558             break;
 559 
 560         case ACPI_RESOURCE_NAME_SERIAL_BUS:
 561 
 562             MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[
 563                 AmlResource->CommonSerialBus.Type];
 564             ExtraStructBytes += AmlResource->CommonSerialBus.ResourceLength -
 565                 MinimumAmlResourceLength;
 566             break;
 567 
 568         default:
 569 
 570             break;
 571         }
 572 
 573         /*
 574          * Update the required buffer size for the internal descriptor structs
 575          *
 576          * Important: Round the size up for the appropriate alignment. This
 577          * is a requirement on IA64.
 578          */
 579         if (AcpiUtGetResourceType (AmlBuffer) == ACPI_RESOURCE_NAME_SERIAL_BUS)
 580         {
 581             BufferSize = AcpiGbl_ResourceStructSerialBusSizes[
 582                 AmlResource->CommonSerialBus.Type] + ExtraStructBytes;
 583         }
 584         else
 585         {
 586             BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] +
 587                         ExtraStructBytes;
 588         }
 589         BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize);
 590 
 591         *SizeNeeded += BufferSize;
 592 
 593         ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES,
 594             "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
 595             AcpiUtGetResourceType (AmlBuffer),
 596             AcpiUtGetDescriptorLength (AmlBuffer), BufferSize));
 597 
 598         /*
 599          * Point to the next resource within the AML stream using the length
 600          * contained in the resource descriptor header
 601          */
 602         AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer);
 603     }
 604 
 605     /* Did not find an EndTag resource descriptor */
 606 
 607     return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
 608 }
 609 
 610 
 611 /*******************************************************************************
 612  *
 613  * FUNCTION:    AcpiRsGetPciRoutingTableLength
 614  *
 615  * PARAMETERS:  PackageObject           - Pointer to the package object
 616  *              BufferSizeNeeded        - UINT32 pointer of the size buffer
 617  *                                        needed to properly return the
 618  *                                        parsed data
 619  *
 620  * RETURN:      Status
 621  *
 622  * DESCRIPTION: Given a package representing a PCI routing table, this
 623  *              calculates the size of the corresponding linked list of
 624  *              descriptions.
 625  *
 626  ******************************************************************************/
 627 
 628 ACPI_STATUS
 629 AcpiRsGetPciRoutingTableLength (
 630     ACPI_OPERAND_OBJECT     *PackageObject,
 631     ACPI_SIZE               *BufferSizeNeeded)
 632 {
 633     UINT32                  NumberOfElements;
 634     ACPI_SIZE               TempSizeNeeded = 0;
 635     ACPI_OPERAND_OBJECT     **TopObjectList;
 636     UINT32                  Index;
 637     ACPI_OPERAND_OBJECT     *PackageElement;
 638     ACPI_OPERAND_OBJECT     **SubObjectList;
 639     BOOLEAN                 NameFound;
 640     UINT32                  TableIndex;
 641 
 642 
 643     ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength);
 644 
 645 
 646     NumberOfElements = PackageObject->Package.Count;
 647 
 648     /*
 649      * Calculate the size of the return buffer.
 650      * The base size is the number of elements * the sizes of the
 651      * structures. Additional space for the strings is added below.
 652      * The minus one is to subtract the size of the UINT8 Source[1]
 653      * member because it is added below.
 654      *
 655      * But each PRT_ENTRY structure has a pointer to a string and
 656      * the size of that string must be found.
 657      */
 658     TopObjectList = PackageObject->Package.Elements;
 659 
 660     for (Index = 0; Index < NumberOfElements; Index++)
 661     {
 662         /* Dereference the sub-package */
 663 
 664         PackageElement = *TopObjectList;
 665 
 666         /* We must have a valid Package object */
 667 
 668         if (!PackageElement ||
 669             (PackageElement->Common.Type != ACPI_TYPE_PACKAGE))
 670         {
 671             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
 672         }
 673 
 674         /*
 675          * The SubObjectList will now point to an array of the
 676          * four IRQ elements: Address, Pin, Source and SourceIndex
 677          */
 678         SubObjectList = PackageElement->Package.Elements;
 679 
 680         /* Scan the IrqTableElements for the Source Name String */
 681 
 682         NameFound = FALSE;
 683 
 684         for (TableIndex = 0;
 685              TableIndex < PackageElement->Package.Count && !NameFound;
 686              TableIndex++)
 687         {
 688             if (*SubObjectList && /* Null object allowed */
 689 
 690                 ((ACPI_TYPE_STRING ==
 691                     (*SubObjectList)->Common.Type) ||
 692 
 693                 ((ACPI_TYPE_LOCAL_REFERENCE ==
 694                     (*SubObjectList)->Common.Type) &&
 695 
 696                     ((*SubObjectList)->Reference.Class ==
 697                         ACPI_REFCLASS_NAME))))
 698             {
 699                 NameFound = TRUE;
 700             }
 701             else
 702             {
 703                 /* Look at the next element */
 704 
 705                 SubObjectList++;
 706             }
 707         }
 708 
 709         TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);
 710 
 711         /* Was a String type found? */
 712 
 713         if (NameFound)
 714         {
 715             if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING)
 716             {
 717                 /*
 718                  * The length String.Length field does not include the
 719                  * terminating NULL, add 1
 720                  */
 721                 TempSizeNeeded += ((ACPI_SIZE)
 722                     (*SubObjectList)->String.Length + 1);
 723             }
 724             else
 725             {
 726                 TempSizeNeeded += AcpiNsGetPathnameLength (
 727                                     (*SubObjectList)->Reference.Node);
 728             }
 729         }
 730         else
 731         {
 732             /*
 733              * If no name was found, then this is a NULL, which is
 734              * translated as a UINT32 zero.
 735              */
 736             TempSizeNeeded += sizeof (UINT32);
 737         }
 738 
 739         /* Round up the size since each element must be aligned */
 740 
 741         TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded);
 742 
 743         /* Point to the next ACPI_OPERAND_OBJECT */
 744 
 745         TopObjectList++;
 746     }
 747 
 748     /*
 749      * Add an extra element to the end of the list, essentially a
 750      * NULL terminator
 751      */
 752     *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE);
 753     return_ACPI_STATUS (AE_OK);
 754 }