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