Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*******************************************************************************
  2.  *
  3.  * Module Name: rscalc - Calculate stream and list lengths
  4.  *
  5.  ******************************************************************************/
  6.  
  7. /*
  8.  * Copyright (C) 2000 - 2015, 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/acpi.h>
  45. #include "accommon.h"
  46. #include "acresrc.h"
  47. #include "acnamesp.h"
  48.  
  49. #define _COMPONENT          ACPI_RESOURCES
  50. ACPI_MODULE_NAME("rscalc")
  51.  
  52. /* Local prototypes */
  53. static u8 acpi_rs_count_set_bits(u16 bit_field);
  54.  
  55. static acpi_rs_length
  56. acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
  57.  
  58. static u32
  59. acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
  60.  
  61. /*******************************************************************************
  62.  *
  63.  * FUNCTION:    acpi_rs_count_set_bits
  64.  *
  65.  * PARAMETERS:  bit_field       - Field in which to count bits
  66.  *
  67.  * RETURN:      Number of bits set within the field
  68.  *
  69.  * DESCRIPTION: Count the number of bits set in a resource field. Used for
  70.  *              (Short descriptor) interrupt and DMA lists.
  71.  *
  72.  ******************************************************************************/
  73.  
  74. static u8 acpi_rs_count_set_bits(u16 bit_field)
  75. {
  76.         u8 bits_set;
  77.  
  78.         ACPI_FUNCTION_ENTRY();
  79.  
  80.         for (bits_set = 0; bit_field; bits_set++) {
  81.  
  82.                 /* Zero the least significant bit that is set */
  83.  
  84.                 bit_field &= (u16) (bit_field - 1);
  85.         }
  86.  
  87.         return (bits_set);
  88. }
  89.  
  90. /*******************************************************************************
  91.  *
  92.  * FUNCTION:    acpi_rs_struct_option_length
  93.  *
  94.  * PARAMETERS:  resource_source     - Pointer to optional descriptor field
  95.  *
  96.  * RETURN:      Status
  97.  *
  98.  * DESCRIPTION: Common code to handle optional resource_source_index and
  99.  *              resource_source fields in some Large descriptors. Used during
  100.  *              list-to-stream conversion
  101.  *
  102.  ******************************************************************************/
  103.  
  104. static acpi_rs_length
  105. acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
  106. {
  107.         ACPI_FUNCTION_ENTRY();
  108.  
  109.         /*
  110.          * If the resource_source string is valid, return the size of the string
  111.          * (string_length includes the NULL terminator) plus the size of the
  112.          * resource_source_index (1).
  113.          */
  114.         if (resource_source->string_ptr) {
  115.                 return ((acpi_rs_length) (resource_source->string_length + 1));
  116.         }
  117.  
  118.         return (0);
  119. }
  120.  
  121. /*******************************************************************************
  122.  *
  123.  * FUNCTION:    acpi_rs_stream_option_length
  124.  *
  125.  * PARAMETERS:  resource_length     - Length from the resource header
  126.  *              minimum_total_length - Minimum length of this resource, before
  127.  *                                    any optional fields. Includes header size
  128.  *
  129.  * RETURN:      Length of optional string (0 if no string present)
  130.  *
  131.  * DESCRIPTION: Common code to handle optional resource_source_index and
  132.  *              resource_source fields in some Large descriptors. Used during
  133.  *              stream-to-list conversion
  134.  *
  135.  ******************************************************************************/
  136.  
  137. static u32
  138. acpi_rs_stream_option_length(u32 resource_length,
  139.                              u32 minimum_aml_resource_length)
  140. {
  141.         u32 string_length = 0;
  142.  
  143.         ACPI_FUNCTION_ENTRY();
  144.  
  145.         /*
  146.          * The resource_source_index and resource_source are optional elements of some
  147.          * Large-type resource descriptors.
  148.          */
  149.  
  150.         /*
  151.          * If the length of the actual resource descriptor is greater than the ACPI
  152.          * spec-defined minimum length, it means that a resource_source_index exists
  153.          * and is followed by a (required) null terminated string. The string length
  154.          * (including the null terminator) is the resource length minus the minimum
  155.          * length, minus one byte for the resource_source_index itself.
  156.          */
  157.         if (resource_length > minimum_aml_resource_length) {
  158.  
  159.                 /* Compute the length of the optional string */
  160.  
  161.                 string_length =
  162.                     resource_length - minimum_aml_resource_length - 1;
  163.         }
  164.  
  165.         /*
  166.          * Round the length up to a multiple of the native word in order to
  167.          * guarantee that the entire resource descriptor is native word aligned
  168.          */
  169.         return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
  170. }
  171.  
  172. /*******************************************************************************
  173.  *
  174.  * FUNCTION:    acpi_rs_get_aml_length
  175.  *
  176.  * PARAMETERS:  resource            - Pointer to the resource linked list
  177.  *              resource_list_size  - Size of the resource linked list
  178.  *              size_needed         - Where the required size is returned
  179.  *
  180.  * RETURN:      Status
  181.  *
  182.  * DESCRIPTION: Takes a linked list of internal resource descriptors and
  183.  *              calculates the size buffer needed to hold the corresponding
  184.  *              external resource byte stream.
  185.  *
  186.  ******************************************************************************/
  187.  
  188. acpi_status
  189. acpi_rs_get_aml_length(struct acpi_resource *resource,
  190.                        acpi_size resource_list_size, acpi_size * size_needed)
  191. {
  192.         acpi_size aml_size_needed = 0;
  193.         struct acpi_resource *resource_end;
  194.         acpi_rs_length total_size;
  195.  
  196.         ACPI_FUNCTION_TRACE(rs_get_aml_length);
  197.  
  198.         /* Traverse entire list of internal resource descriptors */
  199.  
  200.         resource_end =
  201.             ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size);
  202.         while (resource < resource_end) {
  203.  
  204.                 /* Validate the descriptor type */
  205.  
  206.                 if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
  207.                         return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
  208.                 }
  209.  
  210.                 /* Sanity check the length. It must not be zero, or we loop forever */
  211.  
  212.                 if (!resource->length) {
  213.                         return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
  214.                 }
  215.  
  216.                 /* Get the base size of the (external stream) resource descriptor */
  217.  
  218.                 total_size = acpi_gbl_aml_resource_sizes[resource->type];
  219.  
  220.                 /*
  221.                  * Augment the base size for descriptors with optional and/or
  222.                  * variable-length fields
  223.                  */
  224.                 switch (resource->type) {
  225.                 case ACPI_RESOURCE_TYPE_IRQ:
  226.  
  227.                         /* Length can be 3 or 2 */
  228.  
  229.                         if (resource->data.irq.descriptor_length == 2) {
  230.                                 total_size--;
  231.                         }
  232.                         break;
  233.  
  234.                 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
  235.  
  236.                         /* Length can be 1 or 0 */
  237.  
  238.                         if (resource->data.irq.descriptor_length == 0) {
  239.                                 total_size--;
  240.                         }
  241.                         break;
  242.  
  243.                 case ACPI_RESOURCE_TYPE_VENDOR:
  244.                         /*
  245.                          * Vendor Defined Resource:
  246.                          * For a Vendor Specific resource, if the Length is between 1 and 7
  247.                          * it will be created as a Small Resource data type, otherwise it
  248.                          * is a Large Resource data type.
  249.                          */
  250.                         if (resource->data.vendor.byte_length > 7) {
  251.  
  252.                                 /* Base size of a Large resource descriptor */
  253.  
  254.                                 total_size =
  255.                                     sizeof(struct aml_resource_large_header);
  256.                         }
  257.  
  258.                         /* Add the size of the vendor-specific data */
  259.  
  260.                         total_size = (acpi_rs_length)
  261.                             (total_size + resource->data.vendor.byte_length);
  262.                         break;
  263.  
  264.                 case ACPI_RESOURCE_TYPE_END_TAG:
  265.                         /*
  266.                          * End Tag:
  267.                          * We are done -- return the accumulated total size.
  268.                          */
  269.                         *size_needed = aml_size_needed + total_size;
  270.  
  271.                         /* Normal exit */
  272.  
  273.                         return_ACPI_STATUS(AE_OK);
  274.  
  275.                 case ACPI_RESOURCE_TYPE_ADDRESS16:
  276.                         /*
  277.                          * 16-Bit Address Resource:
  278.                          * Add the size of the optional resource_source info
  279.                          */
  280.                         total_size = (acpi_rs_length)
  281.                             (total_size +
  282.                              acpi_rs_struct_option_length(&resource->data.
  283.                                                           address16.
  284.                                                           resource_source));
  285.                         break;
  286.  
  287.                 case ACPI_RESOURCE_TYPE_ADDRESS32:
  288.                         /*
  289.                          * 32-Bit Address Resource:
  290.                          * Add the size of the optional resource_source info
  291.                          */
  292.                         total_size = (acpi_rs_length)
  293.                             (total_size +
  294.                              acpi_rs_struct_option_length(&resource->data.
  295.                                                           address32.
  296.                                                           resource_source));
  297.                         break;
  298.  
  299.                 case ACPI_RESOURCE_TYPE_ADDRESS64:
  300.                         /*
  301.                          * 64-Bit Address Resource:
  302.                          * Add the size of the optional resource_source info
  303.                          */
  304.                         total_size = (acpi_rs_length)
  305.                             (total_size +
  306.                              acpi_rs_struct_option_length(&resource->data.
  307.                                                           address64.
  308.                                                           resource_source));
  309.                         break;
  310.  
  311.                 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
  312.                         /*
  313.                          * Extended IRQ Resource:
  314.                          * Add the size of each additional optional interrupt beyond the
  315.                          * required 1 (4 bytes for each u32 interrupt number)
  316.                          */
  317.                         total_size = (acpi_rs_length)
  318.                             (total_size +
  319.                              ((resource->data.extended_irq.interrupt_count -
  320.                                1) * 4) +
  321.                              /* Add the size of the optional resource_source info */
  322.                              acpi_rs_struct_option_length(&resource->data.
  323.                                                           extended_irq.
  324.                                                           resource_source));
  325.                         break;
  326.  
  327.                 case ACPI_RESOURCE_TYPE_GPIO:
  328.  
  329.                         total_size =
  330.                             (acpi_rs_length) (total_size +
  331.                                               (resource->data.gpio.
  332.                                                pin_table_length * 2) +
  333.                                               resource->data.gpio.
  334.                                               resource_source.string_length +
  335.                                               resource->data.gpio.
  336.                                               vendor_length);
  337.  
  338.                         break;
  339.  
  340.                 case ACPI_RESOURCE_TYPE_SERIAL_BUS:
  341.  
  342.                         total_size =
  343.                             acpi_gbl_aml_resource_serial_bus_sizes[resource->
  344.                                                                    data.
  345.                                                                    common_serial_bus.
  346.                                                                    type];
  347.  
  348.                         total_size = (acpi_rs_length) (total_size +
  349.                                                        resource->data.
  350.                                                        i2c_serial_bus.
  351.                                                        resource_source.
  352.                                                        string_length +
  353.                                                        resource->data.
  354.                                                        i2c_serial_bus.
  355.                                                        vendor_length);
  356.  
  357.                         break;
  358.  
  359.                 default:
  360.  
  361.                         break;
  362.                 }
  363.  
  364.                 /* Update the total */
  365.  
  366.                 aml_size_needed += total_size;
  367.  
  368.                 /* Point to the next object */
  369.  
  370.                 resource =
  371.                     ACPI_ADD_PTR(struct acpi_resource, resource,
  372.                                  resource->length);
  373.         }
  374.  
  375.         /* Did not find an end_tag resource descriptor */
  376.  
  377.         return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
  378. }
  379.  
  380. /*******************************************************************************
  381.  *
  382.  * FUNCTION:    acpi_rs_get_list_length
  383.  *
  384.  * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
  385.  *              aml_buffer_length   - Size of aml_buffer
  386.  *              size_needed         - Where the size needed is returned
  387.  *
  388.  * RETURN:      Status
  389.  *
  390.  * DESCRIPTION: Takes an external resource byte stream and calculates the size
  391.  *              buffer needed to hold the corresponding internal resource
  392.  *              descriptor linked list.
  393.  *
  394.  ******************************************************************************/
  395.  
  396. acpi_status
  397. acpi_rs_get_list_length(u8 * aml_buffer,
  398.                         u32 aml_buffer_length, acpi_size * size_needed)
  399. {
  400.         acpi_status status;
  401.         u8 *end_aml;
  402.         u8 *buffer;
  403.         u32 buffer_size;
  404.         u16 temp16;
  405.         u16 resource_length;
  406.         u32 extra_struct_bytes;
  407.         u8 resource_index;
  408.         u8 minimum_aml_resource_length;
  409.         union aml_resource *aml_resource;
  410.  
  411.         ACPI_FUNCTION_TRACE(rs_get_list_length);
  412.  
  413.         *size_needed = ACPI_RS_SIZE_MIN;        /* Minimum size is one end_tag */
  414.         end_aml = aml_buffer + aml_buffer_length;
  415.  
  416.         /* Walk the list of AML resource descriptors */
  417.  
  418.         while (aml_buffer < end_aml) {
  419.  
  420.                 /* Validate the Resource Type and Resource Length */
  421.  
  422.                 status =
  423.                     acpi_ut_validate_resource(NULL, aml_buffer,
  424.                                               &resource_index);
  425.                 if (ACPI_FAILURE(status)) {
  426.                         /*
  427.                          * Exit on failure. Cannot continue because the descriptor length
  428.                          * may be bogus also.
  429.                          */
  430.                         return_ACPI_STATUS(status);
  431.                 }
  432.  
  433.                 aml_resource = (void *)aml_buffer;
  434.  
  435.                 /* Get the resource length and base (minimum) AML size */
  436.  
  437.                 resource_length = acpi_ut_get_resource_length(aml_buffer);
  438.                 minimum_aml_resource_length =
  439.                     acpi_gbl_resource_aml_sizes[resource_index];
  440.  
  441.                 /*
  442.                  * Augment the size for descriptors with optional
  443.                  * and/or variable length fields
  444.                  */
  445.                 extra_struct_bytes = 0;
  446.                 buffer =
  447.                     aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
  448.  
  449.                 switch (acpi_ut_get_resource_type(aml_buffer)) {
  450.                 case ACPI_RESOURCE_NAME_IRQ:
  451.                         /*
  452.                          * IRQ Resource:
  453.                          * Get the number of bits set in the 16-bit IRQ mask
  454.                          */
  455.                         ACPI_MOVE_16_TO_16(&temp16, buffer);
  456.                         extra_struct_bytes = acpi_rs_count_set_bits(temp16);
  457.                         break;
  458.  
  459.                 case ACPI_RESOURCE_NAME_DMA:
  460.                         /*
  461.                          * DMA Resource:
  462.                          * Get the number of bits set in the 8-bit DMA mask
  463.                          */
  464.                         extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
  465.                         break;
  466.  
  467.                 case ACPI_RESOURCE_NAME_VENDOR_SMALL:
  468.                 case ACPI_RESOURCE_NAME_VENDOR_LARGE:
  469.                         /*
  470.                          * Vendor Resource:
  471.                          * Get the number of vendor data bytes
  472.                          */
  473.                         extra_struct_bytes = resource_length;
  474.  
  475.                         /*
  476.                          * There is already one byte included in the minimum
  477.                          * descriptor size. If there are extra struct bytes,
  478.                          * subtract one from the count.
  479.                          */
  480.                         if (extra_struct_bytes) {
  481.                                 extra_struct_bytes--;
  482.                         }
  483.                         break;
  484.  
  485.                 case ACPI_RESOURCE_NAME_END_TAG:
  486.                         /*
  487.                          * End Tag: This is the normal exit
  488.                          */
  489.                         return_ACPI_STATUS(AE_OK);
  490.  
  491.                 case ACPI_RESOURCE_NAME_ADDRESS32:
  492.                 case ACPI_RESOURCE_NAME_ADDRESS16:
  493.                 case ACPI_RESOURCE_NAME_ADDRESS64:
  494.                         /*
  495.                          * Address Resource:
  496.                          * Add the size of the optional resource_source
  497.                          */
  498.                         extra_struct_bytes =
  499.                             acpi_rs_stream_option_length(resource_length,
  500.                                                          minimum_aml_resource_length);
  501.                         break;
  502.  
  503.                 case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
  504.                         /*
  505.                          * Extended IRQ Resource:
  506.                          * Using the interrupt_table_length, add 4 bytes for each additional
  507.                          * interrupt. Note: at least one interrupt is required and is
  508.                          * included in the minimum descriptor size (reason for the -1)
  509.                          */
  510.                         extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
  511.  
  512.                         /* Add the size of the optional resource_source */
  513.  
  514.                         extra_struct_bytes +=
  515.                             acpi_rs_stream_option_length(resource_length -
  516.                                                          extra_struct_bytes,
  517.                                                          minimum_aml_resource_length);
  518.                         break;
  519.  
  520.                 case ACPI_RESOURCE_NAME_GPIO:
  521.  
  522.                         /* Vendor data is optional */
  523.  
  524.                         if (aml_resource->gpio.vendor_length) {
  525.                                 extra_struct_bytes +=
  526.                                     aml_resource->gpio.vendor_offset -
  527.                                     aml_resource->gpio.pin_table_offset +
  528.                                     aml_resource->gpio.vendor_length;
  529.                         } else {
  530.                                 extra_struct_bytes +=
  531.                                     aml_resource->large_header.resource_length +
  532.                                     sizeof(struct aml_resource_large_header) -
  533.                                     aml_resource->gpio.pin_table_offset;
  534.                         }
  535.                         break;
  536.  
  537.                 case ACPI_RESOURCE_NAME_SERIAL_BUS:
  538.  
  539.                         minimum_aml_resource_length =
  540.                             acpi_gbl_resource_aml_serial_bus_sizes
  541.                             [aml_resource->common_serial_bus.type];
  542.                         extra_struct_bytes +=
  543.                             aml_resource->common_serial_bus.resource_length -
  544.                             minimum_aml_resource_length;
  545.                         break;
  546.  
  547.                 default:
  548.  
  549.                         break;
  550.                 }
  551.  
  552.                 /*
  553.                  * Update the required buffer size for the internal descriptor structs
  554.                  *
  555.                  * Important: Round the size up for the appropriate alignment. This
  556.                  * is a requirement on IA64.
  557.                  */
  558.                 if (acpi_ut_get_resource_type(aml_buffer) ==
  559.                     ACPI_RESOURCE_NAME_SERIAL_BUS) {
  560.                         buffer_size =
  561.                             acpi_gbl_resource_struct_serial_bus_sizes
  562.                             [aml_resource->common_serial_bus.type] +
  563.                             extra_struct_bytes;
  564.                 } else {
  565.                         buffer_size =
  566.                             acpi_gbl_resource_struct_sizes[resource_index] +
  567.                             extra_struct_bytes;
  568.                 }
  569.                 buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
  570.  
  571.                 *size_needed += buffer_size;
  572.  
  573.                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
  574.                                   "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
  575.                                   acpi_ut_get_resource_type(aml_buffer),
  576.                                   acpi_ut_get_descriptor_length(aml_buffer),
  577.                                   buffer_size));
  578.  
  579.                 /*
  580.                  * Point to the next resource within the AML stream using the length
  581.                  * contained in the resource descriptor header
  582.                  */
  583.                 aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
  584.         }
  585.  
  586.         /* Did not find an end_tag resource descriptor */
  587.  
  588.         return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
  589. }
  590.  
  591. /*******************************************************************************
  592.  *
  593.  * FUNCTION:    acpi_rs_get_pci_routing_table_length
  594.  *
  595.  * PARAMETERS:  package_object          - Pointer to the package object
  596.  *              buffer_size_needed      - u32 pointer of the size buffer
  597.  *                                        needed to properly return the
  598.  *                                        parsed data
  599.  *
  600.  * RETURN:      Status
  601.  *
  602.  * DESCRIPTION: Given a package representing a PCI routing table, this
  603.  *              calculates the size of the corresponding linked list of
  604.  *              descriptions.
  605.  *
  606.  ******************************************************************************/
  607.  
  608. acpi_status
  609. acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
  610.                                      acpi_size * buffer_size_needed)
  611. {
  612.         u32 number_of_elements;
  613.         acpi_size temp_size_needed = 0;
  614.         union acpi_operand_object **top_object_list;
  615.         u32 index;
  616.         union acpi_operand_object *package_element;
  617.         union acpi_operand_object **sub_object_list;
  618.         u8 name_found;
  619.         u32 table_index;
  620.  
  621.         ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
  622.  
  623.         number_of_elements = package_object->package.count;
  624.  
  625.         /*
  626.          * Calculate the size of the return buffer.
  627.          * The base size is the number of elements * the sizes of the
  628.          * structures. Additional space for the strings is added below.
  629.          * The minus one is to subtract the size of the u8 Source[1]
  630.          * member because it is added below.
  631.          *
  632.          * But each PRT_ENTRY structure has a pointer to a string and
  633.          * the size of that string must be found.
  634.          */
  635.         top_object_list = package_object->package.elements;
  636.  
  637.         for (index = 0; index < number_of_elements; index++) {
  638.  
  639.                 /* Dereference the subpackage */
  640.  
  641.                 package_element = *top_object_list;
  642.  
  643.                 /* We must have a valid Package object */
  644.  
  645.                 if (!package_element ||
  646.                     (package_element->common.type != ACPI_TYPE_PACKAGE)) {
  647.                         return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
  648.                 }
  649.  
  650.                 /*
  651.                  * The sub_object_list will now point to an array of the
  652.                  * four IRQ elements: Address, Pin, Source and source_index
  653.                  */
  654.                 sub_object_list = package_element->package.elements;
  655.  
  656.                 /* Scan the irq_table_elements for the Source Name String */
  657.  
  658.                 name_found = FALSE;
  659.  
  660.                 for (table_index = 0;
  661.                      table_index < package_element->package.count
  662.                      && !name_found; table_index++) {
  663.                         if (*sub_object_list && /* Null object allowed */
  664.                             ((ACPI_TYPE_STRING ==
  665.                               (*sub_object_list)->common.type) ||
  666.                              ((ACPI_TYPE_LOCAL_REFERENCE ==
  667.                                (*sub_object_list)->common.type) &&
  668.                               ((*sub_object_list)->reference.class ==
  669.                                ACPI_REFCLASS_NAME)))) {
  670.                                 name_found = TRUE;
  671.                         } else {
  672.                                 /* Look at the next element */
  673.  
  674.                                 sub_object_list++;
  675.                         }
  676.                 }
  677.  
  678.                 temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
  679.  
  680.                 /* Was a String type found? */
  681.  
  682.                 if (name_found) {
  683.                         if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) {
  684.                                 /*
  685.                                  * The length String.Length field does not include the
  686.                                  * terminating NULL, add 1
  687.                                  */
  688.                                 temp_size_needed += ((acpi_size)
  689.                                                      (*sub_object_list)->string.
  690.                                                      length + 1);
  691.                         } else {
  692.                                 temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
  693.                         }
  694.                 } else {
  695.                         /*
  696.                          * If no name was found, then this is a NULL, which is
  697.                          * translated as a u32 zero.
  698.                          */
  699.                         temp_size_needed += sizeof(u32);
  700.                 }
  701.  
  702.                 /* Round up the size since each element must be aligned */
  703.  
  704.                 temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
  705.  
  706.                 /* Point to the next union acpi_operand_object */
  707.  
  708.                 top_object_list++;
  709.         }
  710.  
  711.         /*
  712.          * Add an extra element to the end of the list, essentially a
  713.          * NULL terminator
  714.          */
  715.         *buffer_size_needed =
  716.             temp_size_needed + sizeof(struct acpi_pci_routing_table);
  717.         return_ACPI_STATUS(AE_OK);
  718. }
  719.