1 /******************************************************************************* 2 * 3 * Module Name: rscalc - Calculate stream and list lengths 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2020, 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 #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 376 case ACPI_RESOURCE_TYPE_SERIAL_BUS: 377 378 TotalSize = AcpiGbl_AmlResourceSerialBusSizes [ 379 Resource->Data.CommonSerialBus.Type]; 380 381 TotalSize = (ACPI_RS_LENGTH) (TotalSize + 382 Resource->Data.I2cSerialBus.ResourceSource.StringLength + 383 Resource->Data.I2cSerialBus.VendorLength); 384 385 break; 386 387 case ACPI_RESOURCE_TYPE_PIN_CONFIG: 388 389 TotalSize = (ACPI_RS_LENGTH) (TotalSize + 390 (Resource->Data.PinConfig.PinTableLength * 2) + 391 Resource->Data.PinConfig.ResourceSource.StringLength + 392 Resource->Data.PinConfig.VendorLength); 393 394 break; 395 396 case ACPI_RESOURCE_TYPE_PIN_GROUP: 397 398 TotalSize = (ACPI_RS_LENGTH) (TotalSize + 399 (Resource->Data.PinGroup.PinTableLength * 2) + 400 Resource->Data.PinGroup.ResourceLabel.StringLength + 401 Resource->Data.PinGroup.VendorLength); 402 403 break; 404 405 case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION: 406 407 TotalSize = (ACPI_RS_LENGTH) (TotalSize + 408 Resource->Data.PinGroupFunction.ResourceSource.StringLength + 409 Resource->Data.PinGroupFunction.ResourceSourceLabel.StringLength + 410 Resource->Data.PinGroupFunction.VendorLength); 411 412 break; 413 414 case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG: 415 416 TotalSize = (ACPI_RS_LENGTH) (TotalSize + 417 Resource->Data.PinGroupConfig.ResourceSource.StringLength + 418 Resource->Data.PinGroupConfig.ResourceSourceLabel.StringLength + 419 Resource->Data.PinGroupConfig.VendorLength); 420 421 break; 422 423 default: 424 425 break; 426 } 427 428 /* Update the total */ 429 430 AmlSizeNeeded += TotalSize; 431 432 /* Point to the next object */ 433 434 Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length); 435 } 436 437 /* Did not find an EndTag resource descriptor */ 438 439 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 440 } 441 442 443 /******************************************************************************* 444 * 445 * FUNCTION: AcpiRsGetListLength 446 * 447 * PARAMETERS: AmlBuffer - Pointer to the resource byte stream 448 * AmlBufferLength - Size of AmlBuffer 449 * SizeNeeded - Where the size needed is returned 450 * 451 * RETURN: Status 452 * 453 * DESCRIPTION: Takes an external resource byte stream and calculates the size 454 * buffer needed to hold the corresponding internal resource 455 * descriptor linked list. 456 * 457 ******************************************************************************/ 458 459 ACPI_STATUS 460 AcpiRsGetListLength ( 461 UINT8 *AmlBuffer, 462 UINT32 AmlBufferLength, 463 ACPI_SIZE *SizeNeeded) 464 { 465 ACPI_STATUS Status; 466 UINT8 *EndAml; 467 UINT8 *Buffer; 468 UINT32 BufferSize; 469 UINT16 Temp16; 470 UINT16 ResourceLength; 471 UINT32 ExtraStructBytes; 472 UINT8 ResourceIndex; 473 UINT8 MinimumAmlResourceLength; 474 AML_RESOURCE *AmlResource; 475 476 477 ACPI_FUNCTION_TRACE (RsGetListLength); 478 479 480 *SizeNeeded = ACPI_RS_SIZE_MIN; /* Minimum size is one EndTag */ 481 EndAml = AmlBuffer + AmlBufferLength; 482 483 /* Walk the list of AML resource descriptors */ 484 485 while (AmlBuffer < EndAml) 486 { 487 /* Validate the Resource Type and Resource Length */ 488 489 Status = AcpiUtValidateResource (NULL, AmlBuffer, &ResourceIndex); 490 if (ACPI_FAILURE (Status)) 491 { 492 /* 493 * Exit on failure. Cannot continue because the descriptor length 494 * may be bogus also. 495 */ 496 return_ACPI_STATUS (Status); 497 } 498 499 AmlResource = (void *) AmlBuffer; 500 501 /* Get the resource length and base (minimum) AML size */ 502 503 ResourceLength = AcpiUtGetResourceLength (AmlBuffer); 504 MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex]; 505 506 /* 507 * Augment the size for descriptors with optional 508 * and/or variable length fields 509 */ 510 ExtraStructBytes = 0; 511 Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer); 512 513 switch (AcpiUtGetResourceType (AmlBuffer)) 514 { 515 case ACPI_RESOURCE_NAME_IRQ: 516 /* 517 * IRQ Resource: 518 * Get the number of bits set in the 16-bit IRQ mask 519 */ 520 ACPI_MOVE_16_TO_16 (&Temp16, Buffer); 521 ExtraStructBytes = AcpiRsCountSetBits (Temp16); 522 break; 523 524 525 case ACPI_RESOURCE_NAME_DMA: 526 /* 527 * DMA Resource: 528 * Get the number of bits set in the 8-bit DMA mask 529 */ 530 ExtraStructBytes = AcpiRsCountSetBits (*Buffer); 531 break; 532 533 534 case ACPI_RESOURCE_NAME_VENDOR_SMALL: 535 case ACPI_RESOURCE_NAME_VENDOR_LARGE: 536 /* 537 * Vendor Resource: 538 * Get the number of vendor data bytes 539 */ 540 ExtraStructBytes = ResourceLength; 541 542 /* 543 * There is already one byte included in the minimum 544 * descriptor size. If there are extra struct bytes, 545 * subtract one from the count. 546 */ 547 if (ExtraStructBytes) 548 { 549 ExtraStructBytes--; 550 } 551 break; 552 553 554 case ACPI_RESOURCE_NAME_END_TAG: 555 /* 556 * End Tag: This is the normal exit 557 */ 558 return_ACPI_STATUS (AE_OK); 559 560 561 case ACPI_RESOURCE_NAME_ADDRESS32: 562 case ACPI_RESOURCE_NAME_ADDRESS16: 563 case ACPI_RESOURCE_NAME_ADDRESS64: 564 /* 565 * Address Resource: 566 * Add the size of the optional ResourceSource 567 */ 568 ExtraStructBytes = AcpiRsStreamOptionLength ( 569 ResourceLength, MinimumAmlResourceLength); 570 break; 571 572 573 case ACPI_RESOURCE_NAME_EXTENDED_IRQ: 574 /* 575 * Extended IRQ Resource: 576 * Using the InterruptTableLength, add 4 bytes for each additional 577 * interrupt. Note: at least one interrupt is required and is 578 * included in the minimum descriptor size (reason for the -1) 579 */ 580 ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32); 581 582 /* Add the size of the optional ResourceSource */ 583 584 ExtraStructBytes += AcpiRsStreamOptionLength ( 585 ResourceLength - ExtraStructBytes, MinimumAmlResourceLength); 586 break; 587 588 case ACPI_RESOURCE_NAME_GPIO: 589 590 /* Vendor data is optional */ 591 592 if (AmlResource->Gpio.VendorLength) 593 { 594 ExtraStructBytes += 595 AmlResource->Gpio.VendorOffset - 596 AmlResource->Gpio.PinTableOffset + 597 AmlResource->Gpio.VendorLength; 598 } 599 else 600 { 601 ExtraStructBytes += 602 AmlResource->LargeHeader.ResourceLength + 603 sizeof (AML_RESOURCE_LARGE_HEADER) - 604 AmlResource->Gpio.PinTableOffset; 605 } 606 break; 607 608 case ACPI_RESOURCE_NAME_PIN_FUNCTION: 609 610 /* Vendor data is optional */ 611 612 if (AmlResource->PinFunction.VendorLength) 613 { 614 ExtraStructBytes += 615 AmlResource->PinFunction.VendorOffset - 616 AmlResource->PinFunction.PinTableOffset + 617 AmlResource->PinFunction.VendorLength; 618 } 619 else 620 { 621 ExtraStructBytes += 622 AmlResource->LargeHeader.ResourceLength + 623 sizeof (AML_RESOURCE_LARGE_HEADER) - 624 AmlResource->PinFunction.PinTableOffset; 625 } 626 break; 627 628 case ACPI_RESOURCE_NAME_SERIAL_BUS: 629 630 MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[ 631 AmlResource->CommonSerialBus.Type]; 632 ExtraStructBytes += 633 AmlResource->CommonSerialBus.ResourceLength - 634 MinimumAmlResourceLength; 635 break; 636 637 case ACPI_RESOURCE_NAME_PIN_CONFIG: 638 639 /* Vendor data is optional */ 640 641 if (AmlResource->PinConfig.VendorLength) 642 { 643 ExtraStructBytes += 644 AmlResource->PinConfig.VendorOffset - 645 AmlResource->PinConfig.PinTableOffset + 646 AmlResource->PinConfig.VendorLength; 647 } 648 else 649 { 650 ExtraStructBytes += 651 AmlResource->LargeHeader.ResourceLength + 652 sizeof (AML_RESOURCE_LARGE_HEADER) - 653 AmlResource->PinConfig.PinTableOffset; 654 } 655 break; 656 657 case ACPI_RESOURCE_NAME_PIN_GROUP: 658 659 ExtraStructBytes += 660 AmlResource->PinGroup.VendorOffset - 661 AmlResource->PinGroup.PinTableOffset + 662 AmlResource->PinGroup.VendorLength; 663 664 break; 665 666 case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION: 667 668 ExtraStructBytes += 669 AmlResource->PinGroupFunction.VendorOffset - 670 AmlResource->PinGroupFunction.ResSourceOffset + 671 AmlResource->PinGroupFunction.VendorLength; 672 673 break; 674 675 case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG: 676 677 ExtraStructBytes += 678 AmlResource->PinGroupConfig.VendorOffset - 679 AmlResource->PinGroupConfig.ResSourceOffset + 680 AmlResource->PinGroupConfig.VendorLength; 681 682 break; 683 684 default: 685 686 break; 687 } 688 689 /* 690 * Update the required buffer size for the internal descriptor structs 691 * 692 * Important: Round the size up for the appropriate alignment. This 693 * is a requirement on IA64. 694 */ 695 if (AcpiUtGetResourceType (AmlBuffer) == 696 ACPI_RESOURCE_NAME_SERIAL_BUS) 697 { 698 BufferSize = AcpiGbl_ResourceStructSerialBusSizes[ 699 AmlResource->CommonSerialBus.Type] + ExtraStructBytes; 700 } 701 else 702 { 703 BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] + 704 ExtraStructBytes; 705 } 706 707 BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize); 708 *SizeNeeded += BufferSize; 709 710 ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES, 711 "Type %.2X, AmlLength %.2X InternalLength %.2X\n", 712 AcpiUtGetResourceType (AmlBuffer), 713 AcpiUtGetDescriptorLength (AmlBuffer), BufferSize)); 714 715 /* 716 * Point to the next resource within the AML stream using the length 717 * contained in the resource descriptor header 718 */ 719 AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer); 720 } 721 722 /* Did not find an EndTag resource descriptor */ 723 724 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 725 } 726 727 728 /******************************************************************************* 729 * 730 * FUNCTION: AcpiRsGetPciRoutingTableLength 731 * 732 * PARAMETERS: PackageObject - Pointer to the package object 733 * BufferSizeNeeded - UINT32 pointer of the size buffer 734 * needed to properly return the 735 * parsed data 736 * 737 * RETURN: Status 738 * 739 * DESCRIPTION: Given a package representing a PCI routing table, this 740 * calculates the size of the corresponding linked list of 741 * descriptions. 742 * 743 ******************************************************************************/ 744 745 ACPI_STATUS 746 AcpiRsGetPciRoutingTableLength ( 747 ACPI_OPERAND_OBJECT *PackageObject, 748 ACPI_SIZE *BufferSizeNeeded) 749 { 750 UINT32 NumberOfElements; 751 ACPI_SIZE TempSizeNeeded = 0; 752 ACPI_OPERAND_OBJECT **TopObjectList; 753 UINT32 Index; 754 ACPI_OPERAND_OBJECT *PackageElement; 755 ACPI_OPERAND_OBJECT **SubObjectList; 756 BOOLEAN NameFound; 757 UINT32 TableIndex; 758 759 760 ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength); 761 762 763 NumberOfElements = PackageObject->Package.Count; 764 765 /* 766 * Calculate the size of the return buffer. 767 * The base size is the number of elements * the sizes of the 768 * structures. Additional space for the strings is added below. 769 * The minus one is to subtract the size of the UINT8 Source[1] 770 * member because it is added below. 771 * 772 * But each PRT_ENTRY structure has a pointer to a string and 773 * the size of that string must be found. 774 */ 775 TopObjectList = PackageObject->Package.Elements; 776 777 for (Index = 0; Index < NumberOfElements; Index++) 778 { 779 /* Dereference the subpackage */ 780 781 PackageElement = *TopObjectList; 782 783 /* We must have a valid Package object */ 784 785 if (!PackageElement || 786 (PackageElement->Common.Type != ACPI_TYPE_PACKAGE)) 787 { 788 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 789 } 790 791 /* 792 * The SubObjectList will now point to an array of the 793 * four IRQ elements: Address, Pin, Source and SourceIndex 794 */ 795 SubObjectList = PackageElement->Package.Elements; 796 797 /* Scan the IrqTableElements for the Source Name String */ 798 799 NameFound = FALSE; 800 801 for (TableIndex = 0; 802 TableIndex < PackageElement->Package.Count && !NameFound; 803 TableIndex++) 804 { 805 if (*SubObjectList && /* Null object allowed */ 806 807 ((ACPI_TYPE_STRING == 808 (*SubObjectList)->Common.Type) || 809 810 ((ACPI_TYPE_LOCAL_REFERENCE == 811 (*SubObjectList)->Common.Type) && 812 813 ((*SubObjectList)->Reference.Class == 814 ACPI_REFCLASS_NAME)))) 815 { 816 NameFound = TRUE; 817 } 818 else 819 { 820 /* Look at the next element */ 821 822 SubObjectList++; 823 } 824 } 825 826 TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4); 827 828 /* Was a String type found? */ 829 830 if (NameFound) 831 { 832 if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING) 833 { 834 /* 835 * The length String.Length field does not include the 836 * terminating NULL, add 1 837 */ 838 TempSizeNeeded += ((ACPI_SIZE) 839 (*SubObjectList)->String.Length + 1); 840 } 841 else 842 { 843 TempSizeNeeded += AcpiNsGetPathnameLength ( 844 (*SubObjectList)->Reference.Node); 845 } 846 } 847 else 848 { 849 /* 850 * If no name was found, then this is a NULL, which is 851 * translated as a UINT32 zero. 852 */ 853 TempSizeNeeded += sizeof (UINT32); 854 } 855 856 /* Round up the size since each element must be aligned */ 857 858 TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded); 859 860 /* Point to the next ACPI_OPERAND_OBJECT */ 861 862 TopObjectList++; 863 } 864 865 /* 866 * Add an extra element to the end of the list, essentially a 867 * NULL terminator 868 */ 869 *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE); 870 return_ACPI_STATUS (AE_OK); 871 } 872