Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /*******************************************************************************
0003  *
0004  * Module Name: rscalc - Calculate stream and list lengths
0005  *
0006  ******************************************************************************/
0007 
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010 #include "acresrc.h"
0011 #include "acnamesp.h"
0012 
0013 #define _COMPONENT          ACPI_RESOURCES
0014 ACPI_MODULE_NAME("rscalc")
0015 
0016 /* Local prototypes */
0017 static u8 acpi_rs_count_set_bits(u16 bit_field);
0018 
0019 static acpi_rs_length
0020 acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
0021 
0022 static u32
0023 acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
0024 
0025 /*******************************************************************************
0026  *
0027  * FUNCTION:    acpi_rs_count_set_bits
0028  *
0029  * PARAMETERS:  bit_field       - Field in which to count bits
0030  *
0031  * RETURN:      Number of bits set within the field
0032  *
0033  * DESCRIPTION: Count the number of bits set in a resource field. Used for
0034  *              (Short descriptor) interrupt and DMA lists.
0035  *
0036  ******************************************************************************/
0037 
0038 static u8 acpi_rs_count_set_bits(u16 bit_field)
0039 {
0040     u8 bits_set;
0041 
0042     ACPI_FUNCTION_ENTRY();
0043 
0044     for (bits_set = 0; bit_field; bits_set++) {
0045 
0046         /* Zero the least significant bit that is set */
0047 
0048         bit_field &= (u16) (bit_field - 1);
0049     }
0050 
0051     return (bits_set);
0052 }
0053 
0054 /*******************************************************************************
0055  *
0056  * FUNCTION:    acpi_rs_struct_option_length
0057  *
0058  * PARAMETERS:  resource_source     - Pointer to optional descriptor field
0059  *
0060  * RETURN:      Status
0061  *
0062  * DESCRIPTION: Common code to handle optional resource_source_index and
0063  *              resource_source fields in some Large descriptors. Used during
0064  *              list-to-stream conversion
0065  *
0066  ******************************************************************************/
0067 
0068 static acpi_rs_length
0069 acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
0070 {
0071     ACPI_FUNCTION_ENTRY();
0072 
0073     /*
0074      * If the resource_source string is valid, return the size of the string
0075      * (string_length includes the NULL terminator) plus the size of the
0076      * resource_source_index (1).
0077      */
0078     if (resource_source->string_ptr) {
0079         return ((acpi_rs_length)(resource_source->string_length + 1));
0080     }
0081 
0082     return (0);
0083 }
0084 
0085 /*******************************************************************************
0086  *
0087  * FUNCTION:    acpi_rs_stream_option_length
0088  *
0089  * PARAMETERS:  resource_length     - Length from the resource header
0090  *              minimum_total_length - Minimum length of this resource, before
0091  *                                    any optional fields. Includes header size
0092  *
0093  * RETURN:      Length of optional string (0 if no string present)
0094  *
0095  * DESCRIPTION: Common code to handle optional resource_source_index and
0096  *              resource_source fields in some Large descriptors. Used during
0097  *              stream-to-list conversion
0098  *
0099  ******************************************************************************/
0100 
0101 static u32
0102 acpi_rs_stream_option_length(u32 resource_length,
0103                  u32 minimum_aml_resource_length)
0104 {
0105     u32 string_length = 0;
0106 
0107     ACPI_FUNCTION_ENTRY();
0108 
0109     /*
0110      * The resource_source_index and resource_source are optional elements of
0111      * some Large-type resource descriptors.
0112      */
0113 
0114     /*
0115      * If the length of the actual resource descriptor is greater than the
0116      * ACPI spec-defined minimum length, it means that a resource_source_index
0117      * exists and is followed by a (required) null terminated string. The
0118      * string length (including the null terminator) is the resource length
0119      * minus the minimum length, minus one byte for the resource_source_index
0120      * itself.
0121      */
0122     if (resource_length > minimum_aml_resource_length) {
0123 
0124         /* Compute the length of the optional string */
0125 
0126         string_length =
0127             resource_length - minimum_aml_resource_length - 1;
0128     }
0129 
0130     /*
0131      * Round the length up to a multiple of the native word in order to
0132      * guarantee that the entire resource descriptor is native word aligned
0133      */
0134     return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
0135 }
0136 
0137 /*******************************************************************************
0138  *
0139  * FUNCTION:    acpi_rs_get_aml_length
0140  *
0141  * PARAMETERS:  resource            - Pointer to the resource linked list
0142  *              resource_list_size  - Size of the resource linked list
0143  *              size_needed         - Where the required size is returned
0144  *
0145  * RETURN:      Status
0146  *
0147  * DESCRIPTION: Takes a linked list of internal resource descriptors and
0148  *              calculates the size buffer needed to hold the corresponding
0149  *              external resource byte stream.
0150  *
0151  ******************************************************************************/
0152 
0153 acpi_status
0154 acpi_rs_get_aml_length(struct acpi_resource *resource,
0155                acpi_size resource_list_size, acpi_size *size_needed)
0156 {
0157     acpi_size aml_size_needed = 0;
0158     struct acpi_resource *resource_end;
0159     acpi_rs_length total_size;
0160 
0161     ACPI_FUNCTION_TRACE(rs_get_aml_length);
0162 
0163     /* Traverse entire list of internal resource descriptors */
0164 
0165     resource_end =
0166         ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size);
0167     while (resource < resource_end) {
0168 
0169         /* Validate the descriptor type */
0170 
0171         if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
0172             return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
0173         }
0174 
0175         /* Sanity check the length. It must not be zero, or we loop forever */
0176 
0177         if (!resource->length) {
0178             return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
0179         }
0180 
0181         /* Get the base size of the (external stream) resource descriptor */
0182 
0183         total_size = acpi_gbl_aml_resource_sizes[resource->type];
0184 
0185         /*
0186          * Augment the base size for descriptors with optional and/or
0187          * variable-length fields
0188          */
0189         switch (resource->type) {
0190         case ACPI_RESOURCE_TYPE_IRQ:
0191 
0192             /* Length can be 3 or 2 */
0193 
0194             if (resource->data.irq.descriptor_length == 2) {
0195                 total_size--;
0196             }
0197             break;
0198 
0199         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
0200 
0201             /* Length can be 1 or 0 */
0202 
0203             if (resource->data.irq.descriptor_length == 0) {
0204                 total_size--;
0205             }
0206             break;
0207 
0208         case ACPI_RESOURCE_TYPE_VENDOR:
0209             /*
0210              * Vendor Defined Resource:
0211              * For a Vendor Specific resource, if the Length is between 1 and 7
0212              * it will be created as a Small Resource data type, otherwise it
0213              * is a Large Resource data type.
0214              */
0215             if (resource->data.vendor.byte_length > 7) {
0216 
0217                 /* Base size of a Large resource descriptor */
0218 
0219                 total_size =
0220                     sizeof(struct aml_resource_large_header);
0221             }
0222 
0223             /* Add the size of the vendor-specific data */
0224 
0225             total_size = (acpi_rs_length)
0226                 (total_size + resource->data.vendor.byte_length);
0227             break;
0228 
0229         case ACPI_RESOURCE_TYPE_END_TAG:
0230             /*
0231              * End Tag:
0232              * We are done -- return the accumulated total size.
0233              */
0234             *size_needed = aml_size_needed + total_size;
0235 
0236             /* Normal exit */
0237 
0238             return_ACPI_STATUS(AE_OK);
0239 
0240         case ACPI_RESOURCE_TYPE_ADDRESS16:
0241             /*
0242              * 16-Bit Address Resource:
0243              * Add the size of the optional resource_source info
0244              */
0245             total_size = (acpi_rs_length)(total_size +
0246                               acpi_rs_struct_option_length
0247                               (&resource->data.
0248                                address16.
0249                                resource_source));
0250             break;
0251 
0252         case ACPI_RESOURCE_TYPE_ADDRESS32:
0253             /*
0254              * 32-Bit Address Resource:
0255              * Add the size of the optional resource_source info
0256              */
0257             total_size = (acpi_rs_length)(total_size +
0258                               acpi_rs_struct_option_length
0259                               (&resource->data.
0260                                address32.
0261                                resource_source));
0262             break;
0263 
0264         case ACPI_RESOURCE_TYPE_ADDRESS64:
0265             /*
0266              * 64-Bit Address Resource:
0267              * Add the size of the optional resource_source info
0268              */
0269             total_size = (acpi_rs_length)(total_size +
0270                               acpi_rs_struct_option_length
0271                               (&resource->data.
0272                                address64.
0273                                resource_source));
0274             break;
0275 
0276         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
0277             /*
0278              * Extended IRQ Resource:
0279              * Add the size of each additional optional interrupt beyond the
0280              * required 1 (4 bytes for each u32 interrupt number)
0281              */
0282             total_size = (acpi_rs_length)(total_size +
0283                               ((resource->data.
0284                             extended_irq.
0285                             interrupt_count -
0286                             1) * 4) +
0287                               /* Add the size of the optional resource_source info */
0288                               acpi_rs_struct_option_length
0289                               (&resource->data.
0290                                extended_irq.
0291                                resource_source));
0292             break;
0293 
0294         case ACPI_RESOURCE_TYPE_GPIO:
0295 
0296             total_size = (acpi_rs_length)(total_size +
0297                               (resource->data.gpio.
0298                                pin_table_length * 2) +
0299                               resource->data.gpio.
0300                               resource_source.
0301                               string_length +
0302                               resource->data.gpio.
0303                               vendor_length);
0304 
0305             break;
0306 
0307         case ACPI_RESOURCE_TYPE_PIN_FUNCTION:
0308 
0309             total_size = (acpi_rs_length)(total_size +
0310                               (resource->data.
0311                                pin_function.
0312                                pin_table_length * 2) +
0313                               resource->data.
0314                               pin_function.
0315                               resource_source.
0316                               string_length +
0317                               resource->data.
0318                               pin_function.
0319                               vendor_length);
0320 
0321             break;
0322 
0323         case ACPI_RESOURCE_TYPE_SERIAL_BUS:
0324 
0325             total_size =
0326                 acpi_gbl_aml_resource_serial_bus_sizes[resource->
0327                                    data.
0328                                    common_serial_bus.
0329                                    type];
0330 
0331             total_size = (acpi_rs_length)(total_size +
0332                               resource->data.
0333                               i2c_serial_bus.
0334                               resource_source.
0335                               string_length +
0336                               resource->data.
0337                               i2c_serial_bus.
0338                               vendor_length);
0339 
0340             break;
0341 
0342         case ACPI_RESOURCE_TYPE_PIN_CONFIG:
0343 
0344             total_size = (acpi_rs_length)(total_size +
0345                               (resource->data.
0346                                pin_config.
0347                                pin_table_length * 2) +
0348                               resource->data.pin_config.
0349                               resource_source.
0350                               string_length +
0351                               resource->data.pin_config.
0352                               vendor_length);
0353 
0354             break;
0355 
0356         case ACPI_RESOURCE_TYPE_PIN_GROUP:
0357 
0358             total_size = (acpi_rs_length)(total_size +
0359                               (resource->data.pin_group.
0360                                pin_table_length * 2) +
0361                               resource->data.pin_group.
0362                               resource_label.
0363                               string_length +
0364                               resource->data.pin_group.
0365                               vendor_length);
0366 
0367             break;
0368 
0369         case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION:
0370 
0371             total_size = (acpi_rs_length)(total_size +
0372                               resource->data.
0373                               pin_group_function.
0374                               resource_source.
0375                               string_length +
0376                               resource->data.
0377                               pin_group_function.
0378                               resource_source_label.
0379                               string_length +
0380                               resource->data.
0381                               pin_group_function.
0382                               vendor_length);
0383 
0384             break;
0385 
0386         case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG:
0387 
0388             total_size = (acpi_rs_length)(total_size +
0389                               resource->data.
0390                               pin_group_config.
0391                               resource_source.
0392                               string_length +
0393                               resource->data.
0394                               pin_group_config.
0395                               resource_source_label.
0396                               string_length +
0397                               resource->data.
0398                               pin_group_config.
0399                               vendor_length);
0400 
0401             break;
0402 
0403         default:
0404 
0405             break;
0406         }
0407 
0408         /* Update the total */
0409 
0410         aml_size_needed += total_size;
0411 
0412         /* Point to the next object */
0413 
0414         resource =
0415             ACPI_ADD_PTR(struct acpi_resource, resource,
0416                  resource->length);
0417     }
0418 
0419     /* Did not find an end_tag resource descriptor */
0420 
0421     return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
0422 }
0423 
0424 /*******************************************************************************
0425  *
0426  * FUNCTION:    acpi_rs_get_list_length
0427  *
0428  * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
0429  *              aml_buffer_length   - Size of aml_buffer
0430  *              size_needed         - Where the size needed is returned
0431  *
0432  * RETURN:      Status
0433  *
0434  * DESCRIPTION: Takes an external resource byte stream and calculates the size
0435  *              buffer needed to hold the corresponding internal resource
0436  *              descriptor linked list.
0437  *
0438  ******************************************************************************/
0439 
0440 acpi_status
0441 acpi_rs_get_list_length(u8 *aml_buffer,
0442             u32 aml_buffer_length, acpi_size *size_needed)
0443 {
0444     acpi_status status;
0445     u8 *end_aml;
0446     u8 *buffer;
0447     u32 buffer_size;
0448     u16 temp16;
0449     u16 resource_length;
0450     u32 extra_struct_bytes;
0451     u8 resource_index;
0452     u8 minimum_aml_resource_length;
0453     union aml_resource *aml_resource;
0454 
0455     ACPI_FUNCTION_TRACE(rs_get_list_length);
0456 
0457     *size_needed = ACPI_RS_SIZE_MIN;    /* Minimum size is one end_tag */
0458     end_aml = aml_buffer + aml_buffer_length;
0459 
0460     /* Walk the list of AML resource descriptors */
0461 
0462     while (aml_buffer < end_aml) {
0463 
0464         /* Validate the Resource Type and Resource Length */
0465 
0466         status =
0467             acpi_ut_validate_resource(NULL, aml_buffer,
0468                           &resource_index);
0469         if (ACPI_FAILURE(status)) {
0470             /*
0471              * Exit on failure. Cannot continue because the descriptor length
0472              * may be bogus also.
0473              */
0474             return_ACPI_STATUS(status);
0475         }
0476 
0477         aml_resource = (void *)aml_buffer;
0478 
0479         /* Get the resource length and base (minimum) AML size */
0480 
0481         resource_length = acpi_ut_get_resource_length(aml_buffer);
0482         minimum_aml_resource_length =
0483             acpi_gbl_resource_aml_sizes[resource_index];
0484 
0485         /*
0486          * Augment the size for descriptors with optional
0487          * and/or variable length fields
0488          */
0489         extra_struct_bytes = 0;
0490         buffer =
0491             aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
0492 
0493         switch (acpi_ut_get_resource_type(aml_buffer)) {
0494         case ACPI_RESOURCE_NAME_IRQ:
0495             /*
0496              * IRQ Resource:
0497              * Get the number of bits set in the 16-bit IRQ mask
0498              */
0499             ACPI_MOVE_16_TO_16(&temp16, buffer);
0500             extra_struct_bytes = acpi_rs_count_set_bits(temp16);
0501             break;
0502 
0503         case ACPI_RESOURCE_NAME_DMA:
0504             /*
0505              * DMA Resource:
0506              * Get the number of bits set in the 8-bit DMA mask
0507              */
0508             extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
0509             break;
0510 
0511         case ACPI_RESOURCE_NAME_VENDOR_SMALL:
0512         case ACPI_RESOURCE_NAME_VENDOR_LARGE:
0513             /*
0514              * Vendor Resource:
0515              * Get the number of vendor data bytes
0516              */
0517             extra_struct_bytes = resource_length;
0518 
0519             /*
0520              * There is already one byte included in the minimum
0521              * descriptor size. If there are extra struct bytes,
0522              * subtract one from the count.
0523              */
0524             if (extra_struct_bytes) {
0525                 extra_struct_bytes--;
0526             }
0527             break;
0528 
0529         case ACPI_RESOURCE_NAME_END_TAG:
0530             /*
0531              * End Tag: This is the normal exit
0532              */
0533             return_ACPI_STATUS(AE_OK);
0534 
0535         case ACPI_RESOURCE_NAME_ADDRESS32:
0536         case ACPI_RESOURCE_NAME_ADDRESS16:
0537         case ACPI_RESOURCE_NAME_ADDRESS64:
0538             /*
0539              * Address Resource:
0540              * Add the size of the optional resource_source
0541              */
0542             extra_struct_bytes =
0543                 acpi_rs_stream_option_length(resource_length,
0544                              minimum_aml_resource_length);
0545             break;
0546 
0547         case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
0548             /*
0549              * Extended IRQ Resource:
0550              * Using the interrupt_table_length, add 4 bytes for each additional
0551              * interrupt. Note: at least one interrupt is required and is
0552              * included in the minimum descriptor size (reason for the -1)
0553              */
0554             extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
0555 
0556             /* Add the size of the optional resource_source */
0557 
0558             extra_struct_bytes +=
0559                 acpi_rs_stream_option_length(resource_length -
0560                              extra_struct_bytes,
0561                              minimum_aml_resource_length);
0562             break;
0563 
0564         case ACPI_RESOURCE_NAME_GPIO:
0565 
0566             /* Vendor data is optional */
0567 
0568             if (aml_resource->gpio.vendor_length) {
0569                 extra_struct_bytes +=
0570                     aml_resource->gpio.vendor_offset -
0571                     aml_resource->gpio.pin_table_offset +
0572                     aml_resource->gpio.vendor_length;
0573             } else {
0574                 extra_struct_bytes +=
0575                     aml_resource->large_header.resource_length +
0576                     sizeof(struct aml_resource_large_header) -
0577                     aml_resource->gpio.pin_table_offset;
0578             }
0579             break;
0580 
0581         case ACPI_RESOURCE_NAME_PIN_FUNCTION:
0582 
0583             /* Vendor data is optional */
0584 
0585             if (aml_resource->pin_function.vendor_length) {
0586                 extra_struct_bytes +=
0587                     aml_resource->pin_function.vendor_offset -
0588                     aml_resource->pin_function.
0589                     pin_table_offset +
0590                     aml_resource->pin_function.vendor_length;
0591             } else {
0592                 extra_struct_bytes +=
0593                     aml_resource->large_header.resource_length +
0594                     sizeof(struct aml_resource_large_header) -
0595                     aml_resource->pin_function.pin_table_offset;
0596             }
0597             break;
0598 
0599         case ACPI_RESOURCE_NAME_SERIAL_BUS:
0600 
0601             minimum_aml_resource_length =
0602                 acpi_gbl_resource_aml_serial_bus_sizes
0603                 [aml_resource->common_serial_bus.type];
0604             extra_struct_bytes +=
0605                 aml_resource->common_serial_bus.resource_length -
0606                 minimum_aml_resource_length;
0607             break;
0608 
0609         case ACPI_RESOURCE_NAME_PIN_CONFIG:
0610 
0611             /* Vendor data is optional */
0612 
0613             if (aml_resource->pin_config.vendor_length) {
0614                 extra_struct_bytes +=
0615                     aml_resource->pin_config.vendor_offset -
0616                     aml_resource->pin_config.pin_table_offset +
0617                     aml_resource->pin_config.vendor_length;
0618             } else {
0619                 extra_struct_bytes +=
0620                     aml_resource->large_header.resource_length +
0621                     sizeof(struct aml_resource_large_header) -
0622                     aml_resource->pin_config.pin_table_offset;
0623             }
0624             break;
0625 
0626         case ACPI_RESOURCE_NAME_PIN_GROUP:
0627 
0628             extra_struct_bytes +=
0629                 aml_resource->pin_group.vendor_offset -
0630                 aml_resource->pin_group.pin_table_offset +
0631                 aml_resource->pin_group.vendor_length;
0632 
0633             break;
0634 
0635         case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION:
0636 
0637             extra_struct_bytes +=
0638                 aml_resource->pin_group_function.vendor_offset -
0639                 aml_resource->pin_group_function.res_source_offset +
0640                 aml_resource->pin_group_function.vendor_length;
0641 
0642             break;
0643 
0644         case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG:
0645 
0646             extra_struct_bytes +=
0647                 aml_resource->pin_group_config.vendor_offset -
0648                 aml_resource->pin_group_config.res_source_offset +
0649                 aml_resource->pin_group_config.vendor_length;
0650 
0651             break;
0652 
0653         default:
0654 
0655             break;
0656         }
0657 
0658         /*
0659          * Update the required buffer size for the internal descriptor structs
0660          *
0661          * Important: Round the size up for the appropriate alignment. This
0662          * is a requirement on IA64.
0663          */
0664         if (acpi_ut_get_resource_type(aml_buffer) ==
0665             ACPI_RESOURCE_NAME_SERIAL_BUS) {
0666             buffer_size =
0667                 acpi_gbl_resource_struct_serial_bus_sizes
0668                 [aml_resource->common_serial_bus.type] +
0669                 extra_struct_bytes;
0670         } else {
0671             buffer_size =
0672                 acpi_gbl_resource_struct_sizes[resource_index] +
0673                 extra_struct_bytes;
0674         }
0675 
0676         buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
0677         *size_needed += buffer_size;
0678 
0679         ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
0680                   "Type %.2X, AmlLength %.2X InternalLength %.2X%8X\n",
0681                   acpi_ut_get_resource_type(aml_buffer),
0682                   acpi_ut_get_descriptor_length(aml_buffer),
0683                   ACPI_FORMAT_UINT64(*size_needed)));
0684 
0685         /*
0686          * Point to the next resource within the AML stream using the length
0687          * contained in the resource descriptor header
0688          */
0689         aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
0690     }
0691 
0692     /* Did not find an end_tag resource descriptor */
0693 
0694     return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
0695 }
0696 
0697 /*******************************************************************************
0698  *
0699  * FUNCTION:    acpi_rs_get_pci_routing_table_length
0700  *
0701  * PARAMETERS:  package_object          - Pointer to the package object
0702  *              buffer_size_needed      - u32 pointer of the size buffer
0703  *                                        needed to properly return the
0704  *                                        parsed data
0705  *
0706  * RETURN:      Status
0707  *
0708  * DESCRIPTION: Given a package representing a PCI routing table, this
0709  *              calculates the size of the corresponding linked list of
0710  *              descriptions.
0711  *
0712  ******************************************************************************/
0713 
0714 acpi_status
0715 acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
0716                      acpi_size *buffer_size_needed)
0717 {
0718     u32 number_of_elements;
0719     acpi_size temp_size_needed = 0;
0720     union acpi_operand_object **top_object_list;
0721     u32 index;
0722     union acpi_operand_object *package_element;
0723     union acpi_operand_object **sub_object_list;
0724     u8 name_found;
0725     u32 table_index;
0726 
0727     ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
0728 
0729     number_of_elements = package_object->package.count;
0730 
0731     /*
0732      * Calculate the size of the return buffer.
0733      * The base size is the number of elements * the sizes of the
0734      * structures. Additional space for the strings is added below.
0735      * The minus one is to subtract the size of the u8 Source[1]
0736      * member because it is added below.
0737      *
0738      * But each PRT_ENTRY structure has a pointer to a string and
0739      * the size of that string must be found.
0740      */
0741     top_object_list = package_object->package.elements;
0742 
0743     for (index = 0; index < number_of_elements; index++) {
0744 
0745         /* Dereference the subpackage */
0746 
0747         package_element = *top_object_list;
0748 
0749         /* We must have a valid Package object */
0750 
0751         if (!package_element ||
0752             (package_element->common.type != ACPI_TYPE_PACKAGE)) {
0753             return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0754         }
0755 
0756         /*
0757          * The sub_object_list will now point to an array of the
0758          * four IRQ elements: Address, Pin, Source and source_index
0759          */
0760         sub_object_list = package_element->package.elements;
0761 
0762         /* Scan the irq_table_elements for the Source Name String */
0763 
0764         name_found = FALSE;
0765 
0766         for (table_index = 0;
0767              table_index < package_element->package.count
0768              && !name_found; table_index++) {
0769             if (*sub_object_list && /* Null object allowed */
0770                 ((ACPI_TYPE_STRING ==
0771                   (*sub_object_list)->common.type) ||
0772                  ((ACPI_TYPE_LOCAL_REFERENCE ==
0773                    (*sub_object_list)->common.type) &&
0774                   ((*sub_object_list)->reference.class ==
0775                    ACPI_REFCLASS_NAME)))) {
0776                 name_found = TRUE;
0777             } else {
0778                 /* Look at the next element */
0779 
0780                 sub_object_list++;
0781             }
0782         }
0783 
0784         temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
0785 
0786         /* Was a String type found? */
0787 
0788         if (name_found) {
0789             if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) {
0790                 /*
0791                  * The length String.Length field does not include the
0792                  * terminating NULL, add 1
0793                  */
0794                 temp_size_needed += ((acpi_size)
0795                              (*sub_object_list)->string.
0796                              length + 1);
0797             } else {
0798                 temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
0799             }
0800         } else {
0801             /*
0802              * If no name was found, then this is a NULL, which is
0803              * translated as a u32 zero.
0804              */
0805             temp_size_needed += sizeof(u32);
0806         }
0807 
0808         /* Round up the size since each element must be aligned */
0809 
0810         temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
0811 
0812         /* Point to the next union acpi_operand_object */
0813 
0814         top_object_list++;
0815     }
0816 
0817     /*
0818      * Add an extra element to the end of the list, essentially a
0819      * NULL terminator
0820      */
0821     *buffer_size_needed =
0822         temp_size_needed + sizeof(struct acpi_pci_routing_table);
0823     return_ACPI_STATUS(AE_OK);
0824 }