1 /******************************************************************************* 2 * 3 * Module Name: rscalc - Calculate stream and list lengths 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2025, 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 637 MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[ 638 AmlResource->CommonSerialBus.Type]; 639 ExtraStructBytes += 640 AmlResource->CommonSerialBus.ResourceLength - 641 MinimumAmlResourceLength; 642 break; 643 } 644 645 case ACPI_RESOURCE_NAME_PIN_CONFIG: 646 647 /* Vendor data is optional */ 648 649 if (AmlResource->PinConfig.VendorLength) 650 { 651 ExtraStructBytes += 652 AmlResource->PinConfig.VendorOffset - 653 AmlResource->PinConfig.PinTableOffset + 654 AmlResource->PinConfig.VendorLength; 655 } 656 else 657 { 658 ExtraStructBytes += 659 AmlResource->LargeHeader.ResourceLength + 660 sizeof (AML_RESOURCE_LARGE_HEADER) - 661 AmlResource->PinConfig.PinTableOffset; 662 } 663 break; 664 665 case ACPI_RESOURCE_NAME_PIN_GROUP: 666 667 ExtraStructBytes += 668 AmlResource->PinGroup.VendorOffset - 669 AmlResource->PinGroup.PinTableOffset + 670 AmlResource->PinGroup.VendorLength; 671 672 break; 673 674 case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION: 675 676 ExtraStructBytes += 677 AmlResource->PinGroupFunction.VendorOffset - 678 AmlResource->PinGroupFunction.ResSourceOffset + 679 AmlResource->PinGroupFunction.VendorLength; 680 681 break; 682 683 case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG: 684 685 ExtraStructBytes += 686 AmlResource->PinGroupConfig.VendorOffset - 687 AmlResource->PinGroupConfig.ResSourceOffset + 688 AmlResource->PinGroupConfig.VendorLength; 689 690 break; 691 692 case ACPI_RESOURCE_NAME_CLOCK_INPUT: 693 ExtraStructBytes = AcpiRsStreamOptionLength ( 694 ResourceLength, MinimumAmlResourceLength); 695 696 break; 697 698 default: 699 700 break; 701 } 702 703 /* 704 * Update the required buffer size for the internal descriptor structs 705 * 706 * Important: Round the size up for the appropriate alignment. This 707 * is a requirement on IA64. 708 */ 709 if (AcpiUtGetResourceType (AmlBuffer) == 710 ACPI_RESOURCE_NAME_SERIAL_BUS) 711 { 712 BufferSize = AcpiGbl_ResourceStructSerialBusSizes[ 713 AmlResource->CommonSerialBus.Type] + ExtraStructBytes; 714 } 715 else 716 { 717 BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] + 718 ExtraStructBytes; 719 } 720 721 BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize); 722 *SizeNeeded += BufferSize; 723 724 ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES, 725 "Type %.2X, AmlLength %.2X InternalLength %.2X%8X\n", 726 AcpiUtGetResourceType (AmlBuffer), 727 AcpiUtGetDescriptorLength (AmlBuffer), ACPI_FORMAT_UINT64(*SizeNeeded))); 728 729 /* 730 * Point to the next resource within the AML stream using the length 731 * contained in the resource descriptor header 732 */ 733 AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer); 734 } 735 736 /* Did not find an EndTag resource descriptor */ 737 738 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 739 } 740 741 742 /******************************************************************************* 743 * 744 * FUNCTION: AcpiRsGetPciRoutingTableLength 745 * 746 * PARAMETERS: PackageObject - Pointer to the package object 747 * BufferSizeNeeded - UINT32 pointer of the size buffer 748 * needed to properly return the 749 * parsed data 750 * 751 * RETURN: Status 752 * 753 * DESCRIPTION: Given a package representing a PCI routing table, this 754 * calculates the size of the corresponding linked list of 755 * descriptions. 756 * 757 ******************************************************************************/ 758 759 ACPI_STATUS 760 AcpiRsGetPciRoutingTableLength ( 761 ACPI_OPERAND_OBJECT *PackageObject, 762 ACPI_SIZE *BufferSizeNeeded) 763 { 764 UINT32 NumberOfElements; 765 ACPI_SIZE TempSizeNeeded = 0; 766 ACPI_OPERAND_OBJECT **TopObjectList; 767 UINT32 Index; 768 ACPI_OPERAND_OBJECT *PackageElement; 769 ACPI_OPERAND_OBJECT **SubObjectList; 770 BOOLEAN NameFound; 771 UINT32 TableIndex; 772 773 774 ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength); 775 776 777 NumberOfElements = PackageObject->Package.Count; 778 779 /* 780 * Calculate the size of the return buffer. 781 * The base size is the number of elements * the sizes of the 782 * structures. Additional space for the strings is added below. 783 * The minus one is to subtract the size of the UINT8 Source[1] 784 * member because it is added below. 785 * 786 * But each PRT_ENTRY structure has a pointer to a string and 787 * the size of that string must be found. 788 */ 789 TopObjectList = PackageObject->Package.Elements; 790 791 for (Index = 0; Index < NumberOfElements; Index++) 792 { 793 /* Dereference the subpackage */ 794 795 PackageElement = *TopObjectList; 796 797 /* We must have a valid Package object */ 798 799 if (!PackageElement || 800 (PackageElement->Common.Type != ACPI_TYPE_PACKAGE)) 801 { 802 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 803 } 804 805 /* 806 * The SubObjectList will now point to an array of the 807 * four IRQ elements: Address, Pin, Source and SourceIndex 808 */ 809 SubObjectList = PackageElement->Package.Elements; 810 811 /* Scan the IrqTableElements for the Source Name String */ 812 813 NameFound = FALSE; 814 815 for (TableIndex = 0; 816 TableIndex < PackageElement->Package.Count && !NameFound; 817 TableIndex++) 818 { 819 if (*SubObjectList && /* Null object allowed */ 820 821 ((ACPI_TYPE_STRING == 822 (*SubObjectList)->Common.Type) || 823 824 ((ACPI_TYPE_LOCAL_REFERENCE == 825 (*SubObjectList)->Common.Type) && 826 827 ((*SubObjectList)->Reference.Class == 828 ACPI_REFCLASS_NAME)))) 829 { 830 NameFound = TRUE; 831 } 832 else 833 { 834 /* Look at the next element */ 835 836 SubObjectList++; 837 } 838 } 839 840 TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4); 841 842 /* Was a String type found? */ 843 844 if (NameFound) 845 { 846 if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING) 847 { 848 /* 849 * The length String.Length field does not include the 850 * terminating NULL, add 1 851 */ 852 TempSizeNeeded += ((ACPI_SIZE) 853 (*SubObjectList)->String.Length + 1); 854 } 855 else 856 { 857 TempSizeNeeded += AcpiNsGetPathnameLength ( 858 (*SubObjectList)->Reference.Node); 859 } 860 } 861 else 862 { 863 /* 864 * If no name was found, then this is a NULL, which is 865 * translated as a UINT32 zero. 866 */ 867 TempSizeNeeded += sizeof (UINT32); 868 } 869 870 /* Round up the size since each element must be aligned */ 871 872 TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded); 873 874 /* Point to the next ACPI_OPERAND_OBJECT */ 875 876 TopObjectList++; 877 } 878 879 /* 880 * Add an extra element to the end of the list, essentially a 881 * NULL terminator 882 */ 883 *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE); 884 return_ACPI_STATUS (AE_OK); 885 } 886