2da7c6a8182e97a62b45e801346bd0f7ead25733
[linux-2.6.git] / drivers / acpi / resources / rscalc.c
1 /*******************************************************************************
2  *
3  * Module Name: rscalc - Calculate stream and list lengths
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2005, R. Byron Moore
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 <acpi/acresrc.h>
46 #include <acpi/amlcode.h>
47 #include <acpi/amlresrc.h>
48 #include <acpi/acnamesp.h>
49
50 #define _COMPONENT          ACPI_RESOURCES
51 ACPI_MODULE_NAME("rscalc")
52
53 /*
54  * Base sizes for external resource descriptors, indexed by internal type.
55  * Includes size of the descriptor header (1 byte for small descriptors,
56  * 3 bytes for large descriptors)
57  */
58 static u8 acpi_gbl_stream_sizes[] = {
59         4,                      /* ACPI_RSTYPE_IRQ (Byte 3 is optional, but always created) */
60         3,                      /* ACPI_RSTYPE_DMA */
61         2,                      /* ACPI_RSTYPE_START_DPF (Byte 1 is optional, but always created) */
62         1,                      /* ACPI_RSTYPE_END_DPF */
63         8,                      /* ACPI_RSTYPE_IO */
64         4,                      /* ACPI_RSTYPE_FIXED_IO */
65         1,                      /* ACPI_RSTYPE_VENDOR */
66         2,                      /* ACPI_RSTYPE_END_TAG */
67         12,                     /* ACPI_RSTYPE_MEM24 */
68         20,                     /* ACPI_RSTYPE_MEM32 */
69         12,                     /* ACPI_RSTYPE_FIXED_MEM32 */
70         16,                     /* ACPI_RSTYPE_ADDRESS16 */
71         26,                     /* ACPI_RSTYPE_ADDRESS32 */
72         46,                     /* ACPI_RSTYPE_ADDRESS64 */
73         9,                      /* ACPI_RSTYPE_EXT_IRQ */
74         15                      /* ACPI_RSTYPE_GENERIC_REG */
75 };
76
77 /*
78  * Base sizes of resource descriptors, both the actual AML stream length and
79  * size of the internal struct representation.
80  */
81 struct acpi_resource_sizes {
82         u8 minimum_stream_size;
83         u8 minimum_struct_size;
84 };
85
86 static struct acpi_resource_sizes acpi_gbl_sm_resource_sizes[] = {
87         {0, 0},                 /* 0x00, Reserved */
88         {0, 0},                 /* 0x01, Reserved */
89         {0, 0},                 /* 0x02, Reserved */
90         {0, 0},                 /* 0x03, Reserved */
91         {3, ACPI_SIZEOF_RESOURCE(struct acpi_resource_irq)},    /* ACPI_RDESC_TYPE_IRQ_FORMAT */
92         {3, ACPI_SIZEOF_RESOURCE(struct acpi_resource_dma)},    /* ACPI_RDESC_TYPE_DMA_FORMAT */
93         {1, ACPI_SIZEOF_RESOURCE(struct acpi_resource_start_dpf)},      /* ACPI_RDESC_TYPE_START_DEPENDENT */
94         {1, ACPI_RESOURCE_LENGTH},      /* ACPI_RDESC_TYPE_END_DEPENDENT */
95         {8, ACPI_SIZEOF_RESOURCE(struct acpi_resource_io)},     /* ACPI_RDESC_TYPE_IO_PORT */
96         {4, ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_io)},       /* ACPI_RDESC_TYPE_FIXED_IO_PORT */
97         {0, 0},                 /* 0x0A, Reserved */
98         {0, 0},                 /* 0x0B, Reserved */
99         {0, 0},                 /* 0x0C, Reserved */
100         {0, 0},                 /* 0x0D, Reserved */
101         {1, ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor)}, /* ACPI_RDESC_TYPE_SMALL_VENDOR */
102         {2, ACPI_RESOURCE_LENGTH},      /* ACPI_RDESC_TYPE_END_TAG */
103 };
104
105 static struct acpi_resource_sizes acpi_gbl_lg_resource_sizes[] = {
106         {0, 0},                 /* 0x00, Reserved */
107         {12, ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem24)}, /* ACPI_RDESC_TYPE_MEMORY_24 */
108         {15, ACPI_SIZEOF_RESOURCE(struct acpi_resource_generic_reg)},   /* ACPI_RDESC_TYPE_GENERIC_REGISTER */
109         {0, 0},                 /* 0x03, Reserved */
110         {3, ACPI_SIZEOF_RESOURCE(struct acpi_resource_vendor)}, /* ACPI_RDESC_TYPE_LARGE_VENDOR */
111         {20, ACPI_SIZEOF_RESOURCE(struct acpi_resource_mem32)}, /* ACPI_RDESC_TYPE_MEMORY_32 */
112         {12, ACPI_SIZEOF_RESOURCE(struct acpi_resource_fixed_mem32)},   /* ACPI_RDESC_TYPE_FIXED_MEMORY_32 */
113         {26, ACPI_SIZEOF_RESOURCE(struct acpi_resource_address32)},     /* ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE */
114         {16, ACPI_SIZEOF_RESOURCE(struct acpi_resource_address16)},     /* ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE */
115         {9, ACPI_SIZEOF_RESOURCE(struct acpi_resource_ext_irq)},        /* ACPI_RDESC_TYPE_EXTENDED_XRUPT */
116         {46, ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64)},     /* ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE */
117         {56, ACPI_SIZEOF_RESOURCE(struct acpi_resource_address64)},     /* ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE */
118 };
119
120 /* Local prototypes */
121
122 static u8 acpi_rs_count_set_bits(u16 bit_field);
123
124 static struct acpi_resource_sizes *acpi_rs_get_resource_sizes(u8 resource_type);
125
126 static u16 acpi_rs_get_resource_length(u8 * resource);
127
128 static acpi_size
129 acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
130
131 static u32
132 acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
133
134 /*******************************************************************************
135  *
136  * FUNCTION:    acpi_rs_count_set_bits
137  *
138  * PARAMETERS:  bit_field       - Field in which to count bits
139  *
140  * RETURN:      Number of bits set within the field
141  *
142  * DESCRIPTION: Count the number of bits set in a resource field. Used for
143  *              (Short descriptor) interrupt and DMA lists.
144  *
145  ******************************************************************************/
146
147 static u8 acpi_rs_count_set_bits(u16 bit_field)
148 {
149         u8 bits_set;
150
151         ACPI_FUNCTION_ENTRY();
152
153         for (bits_set = 0; bit_field; bits_set++) {
154                 /* Zero the least significant bit that is set */
155
156                 bit_field &= (bit_field - 1);
157         }
158
159         return (bits_set);
160 }
161
162 /*******************************************************************************
163  *
164  * FUNCTION:    acpi_rs_get_resource_sizes
165  *
166  * PARAMETERS:  resource_type       - Byte 0 of a resource descriptor
167  *
168  * RETURN:      Pointer to the resource conversion handler
169  *
170  * DESCRIPTION: Extract the Resource Type/Name from the first byte of
171  *              a resource descriptor.
172  *
173  ******************************************************************************/
174
175 static struct acpi_resource_sizes *acpi_rs_get_resource_sizes(u8 resource_type)
176 {
177         struct acpi_resource_sizes *size_info;
178
179         ACPI_FUNCTION_ENTRY();
180
181         /* Determine if this is a small or large resource */
182
183         if (resource_type & ACPI_RDESC_TYPE_LARGE) {
184                 /* Large Resource Type -- bits 6:0 contain the name */
185
186                 if (resource_type > ACPI_RDESC_LARGE_MAX) {
187                         return (NULL);
188                 }
189
190                 size_info = &acpi_gbl_lg_resource_sizes[(resource_type &
191                                                          ACPI_RDESC_LARGE_MASK)];
192         } else {
193                 /* Small Resource Type -- bits 6:3 contain the name */
194
195                 size_info = &acpi_gbl_sm_resource_sizes[((resource_type &
196                                                           ACPI_RDESC_SMALL_MASK)
197                                                          >> 3)];
198         }
199
200         /* Zero entry indicates an invalid resource type */
201
202         if (!size_info->minimum_stream_size) {
203                 return (NULL);
204         }
205
206         return (size_info);
207 }
208
209 /*******************************************************************************
210  *
211  * FUNCTION:    acpi_rs_get_resource_length
212  *
213  * PARAMETERS:  Resource            - Pointer to the resource descriptor
214  *
215  * RETURN:      Byte length of the (AML byte stream) descriptor. By definition,
216  *              this does not include the size of the descriptor header and the
217  *              length field itself.
218  *
219  * DESCRIPTION: Extract the length of a resource descriptor.
220  *
221  ******************************************************************************/
222
223 static u16 acpi_rs_get_resource_length(u8 * resource)
224 {
225         u16 resource_length;
226
227         ACPI_FUNCTION_ENTRY();
228
229         /* Determine if this is a small or large resource */
230
231         if (*resource & ACPI_RDESC_TYPE_LARGE) {
232                 /* Large Resource type -- length is in bytes 1-2 */
233
234                 ACPI_MOVE_16_TO_16(&resource_length, (resource + 1));
235
236         } else {
237                 /* Small Resource Type -- bits 2:0 of byte 0 contain the length */
238
239                 resource_length =
240                     (u16) (*resource & ACPI_RDESC_SMALL_LENGTH_MASK);
241         }
242
243         return (resource_length);
244 }
245
246 /*******************************************************************************
247  *
248  * FUNCTION:    acpi_rs_struct_option_length
249  *
250  * PARAMETERS:  resource_source     - Pointer to optional descriptor field
251  *
252  * RETURN:      Status
253  *
254  * DESCRIPTION: Common code to handle optional resource_source_index and
255  *              resource_source fields in some Large descriptors. Used during
256  *              list-to-stream conversion
257  *
258  ******************************************************************************/
259
260 static acpi_size
261 acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
262 {
263         ACPI_FUNCTION_ENTRY();
264
265         /*
266          * If the resource_source string is valid, return the size of the string
267          * (string_length includes the NULL terminator) plus the size of the
268          * resource_source_index (1).
269          */
270         if (resource_source->string_ptr) {
271                 return ((acpi_size) resource_source->string_length + 1);
272         }
273
274         return (0);
275 }
276
277 /*******************************************************************************
278  *
279  * FUNCTION:    acpi_rs_stream_option_length
280  *
281  * PARAMETERS:  resource_length     - Length from the resource header
282  *              minimum_total_length - Minimum length of this resource, before
283  *                                    any optional fields. Includes header size
284  *
285  * RETURN:      Length of optional string (0 if no string present)
286  *
287  * DESCRIPTION: Common code to handle optional resource_source_index and
288  *              resource_source fields in some Large descriptors. Used during
289  *              stream-to-list conversion
290  *
291  ******************************************************************************/
292
293 static u32
294 acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length)
295 {
296         u32 string_length = 0;
297         u32 minimum_resource_length;
298
299         ACPI_FUNCTION_ENTRY();
300
301         /*
302          * The resource_source_index and resource_source are optional elements of some
303          * Large-type resource descriptors.
304          */
305
306         /* Compute minimum size of the data part of the resource descriptor */
307
308         minimum_resource_length =
309             minimum_total_length - sizeof(struct asl_large_header);
310
311         /*
312          * If the length of the actual resource descriptor is greater than the ACPI
313          * spec-defined minimum length, it means that a resource_source_index exists
314          * and is followed by a (required) null terminated string. The string length
315          * (including the null terminator) is the resource length minus the minimum
316          * length, minus one byte for the resource_source_index itself.
317          */
318         if (resource_length > minimum_resource_length) {
319                 /* Compute the length of the optional string */
320
321                 string_length = resource_length - minimum_resource_length - 1;
322         }
323
324         /* Round up length to 32 bits for internal structure alignment */
325
326         return (ACPI_ROUND_UP_to_32_bITS(string_length));
327 }
328
329 /*******************************************************************************
330  *
331  * FUNCTION:    acpi_rs_get_byte_stream_length
332  *
333  * PARAMETERS:  Resource            - Pointer to the resource linked list
334  *              size_needed         - Where the required size is returned
335  *
336  * RETURN:      Status
337  *
338  * DESCRIPTION: Takes a linked list of internal resource descriptors and
339  *              calculates the size buffer needed to hold the corresponding
340  *              external resource byte stream.
341  *
342  ******************************************************************************/
343
344 acpi_status
345 acpi_rs_get_byte_stream_length(struct acpi_resource * resource,
346                                acpi_size * size_needed)
347 {
348         acpi_size byte_stream_size_needed = 0;
349         acpi_size segment_size;
350
351         ACPI_FUNCTION_TRACE("rs_get_byte_stream_length");
352
353         /* Traverse entire list of internal resource descriptors */
354
355         while (resource) {
356                 /* Validate the descriptor type */
357
358                 if (resource->type > ACPI_RSTYPE_MAX) {
359                         return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
360                 }
361
362                 /* Get the base size of the (external stream) resource descriptor */
363
364                 segment_size = acpi_gbl_stream_sizes[resource->type];
365
366                 /*
367                  * Augment the base size for descriptors with optional and/or
368                  * variable-length fields
369                  */
370                 switch (resource->type) {
371                 case ACPI_RSTYPE_VENDOR:
372                         /*
373                          * Vendor Defined Resource:
374                          * For a Vendor Specific resource, if the Length is between 1 and 7
375                          * it will be created as a Small Resource data type, otherwise it
376                          * is a Large Resource data type.
377                          */
378                         if (resource->data.vendor_specific.length > 7) {
379                                 /* Base size of a Large resource descriptor */
380
381                                 segment_size = 3;
382                         }
383
384                         /* Add the size of the vendor-specific data */
385
386                         segment_size += resource->data.vendor_specific.length;
387                         break;
388
389                 case ACPI_RSTYPE_END_TAG:
390                         /*
391                          * End Tag:
392                          * We are done -- return the accumulated total size.
393                          */
394                         *size_needed = byte_stream_size_needed + segment_size;
395
396                         /* Normal exit */
397
398                         return_ACPI_STATUS(AE_OK);
399
400                 case ACPI_RSTYPE_ADDRESS16:
401                         /*
402                          * 16-Bit Address Resource:
403                          * Add the size of the optional resource_source info
404                          */
405                         segment_size +=
406                             acpi_rs_struct_option_length(&resource->data.
407                                                          address16.
408                                                          resource_source);
409                         break;
410
411                 case ACPI_RSTYPE_ADDRESS32:
412                         /*
413                          * 32-Bit Address Resource:
414                          * Add the size of the optional resource_source info
415                          */
416                         segment_size +=
417                             acpi_rs_struct_option_length(&resource->data.
418                                                          address32.
419                                                          resource_source);
420                         break;
421
422                 case ACPI_RSTYPE_ADDRESS64:
423                         /*
424                          * 64-Bit Address Resource:
425                          * Add the size of the optional resource_source info
426                          */
427                         segment_size +=
428                             acpi_rs_struct_option_length(&resource->data.
429                                                          address64.
430                                                          resource_source);
431                         break;
432
433                 case ACPI_RSTYPE_EXT_IRQ:
434                         /*
435                          * Extended IRQ Resource:
436                          * Add the size of each additional optional interrupt beyond the
437                          * required 1 (4 bytes for each u32 interrupt number)
438                          */
439                         segment_size += (((acpi_size)
440                                           resource->data.extended_irq.
441                                           number_of_interrupts - 1) * 4);
442
443                         /* Add the size of the optional resource_source info */
444
445                         segment_size +=
446                             acpi_rs_struct_option_length(&resource->data.
447                                                          extended_irq.
448                                                          resource_source);
449                         break;
450
451                 default:
452                         break;
453                 }
454
455                 /* Update the total */
456
457                 byte_stream_size_needed += segment_size;
458
459                 /* Point to the next object */
460
461                 resource = ACPI_PTR_ADD(struct acpi_resource,
462                                         resource, resource->length);
463         }
464
465         /* Did not find an END_TAG descriptor */
466
467         return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
468 }
469
470 /*******************************************************************************
471  *
472  * FUNCTION:    acpi_rs_get_list_length
473  *
474  * PARAMETERS:  byte_stream_buffer      - Pointer to the resource byte stream
475  *              byte_stream_buffer_length - Size of byte_stream_buffer
476  *              size_needed             - Where the size needed is returned
477  *
478  * RETURN:      Status
479  *
480  * DESCRIPTION: Takes an external resource byte stream and calculates the size
481  *              buffer needed to hold the corresponding internal resource
482  *              descriptor linked list.
483  *
484  ******************************************************************************/
485
486 acpi_status
487 acpi_rs_get_list_length(u8 * byte_stream_buffer,
488                         u32 byte_stream_buffer_length, acpi_size * size_needed)
489 {
490         u8 *buffer;
491         struct acpi_resource_sizes *resource_info;
492         u32 buffer_size = 0;
493         u32 bytes_parsed = 0;
494         u8 resource_type;
495         u16 temp16;
496         u16 resource_length;
497         u16 header_length;
498         u32 extra_struct_bytes;
499
500         ACPI_FUNCTION_TRACE("rs_get_list_length");
501
502         while (bytes_parsed < byte_stream_buffer_length) {
503                 /* The next byte in the stream is the resource descriptor type */
504
505                 resource_type = acpi_rs_get_resource_type(*byte_stream_buffer);
506
507                 /* Get the base stream size and structure sizes for the descriptor */
508
509                 resource_info = acpi_rs_get_resource_sizes(resource_type);
510                 if (!resource_info) {
511                         return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
512                 }
513
514                 /* Get the Length field from the input resource descriptor */
515
516                 resource_length =
517                     acpi_rs_get_resource_length(byte_stream_buffer);
518
519                 /* Augment the size for descriptors with optional fields */
520
521                 extra_struct_bytes = 0;
522
523                 if (!(resource_type & ACPI_RDESC_TYPE_LARGE)) {
524                         /*
525                          * Small resource descriptors
526                          */
527                         header_length = 1;
528                         buffer = byte_stream_buffer + header_length;
529
530                         switch (resource_type) {
531                         case ACPI_RDESC_TYPE_IRQ_FORMAT:
532                                 /*
533                                  * IRQ Resource:
534                                  * Get the number of bits set in the IRQ word
535                                  */
536                                 ACPI_MOVE_16_TO_16(&temp16, buffer);
537
538                                 extra_struct_bytes =
539                                     (acpi_rs_count_set_bits(temp16) *
540                                      sizeof(u32));
541                                 break;
542
543                         case ACPI_RDESC_TYPE_DMA_FORMAT:
544                                 /*
545                                  * DMA Resource:
546                                  * Get the number of bits set in the DMA channels byte
547                                  */
548                                 extra_struct_bytes =
549                                     (acpi_rs_count_set_bits((u16) * buffer) *
550                                      sizeof(u32));
551                                 break;
552
553                         case ACPI_RDESC_TYPE_SMALL_VENDOR:
554                                 /*
555                                  * Vendor Specific Resource:
556                                  * Ensure a 32-bit boundary for the structure
557                                  */
558                                 extra_struct_bytes =
559                                     ACPI_ROUND_UP_to_32_bITS(resource_length);
560                                 break;
561
562                         case ACPI_RDESC_TYPE_END_TAG:
563                                 /*
564                                  * End Tag:
565                                  * Terminate the loop now
566                                  */
567                                 byte_stream_buffer_length = bytes_parsed;
568                                 break;
569
570                         default:
571                                 break;
572                         }
573                 } else {
574                         /*
575                          * Large resource descriptors
576                          */
577                         header_length = sizeof(struct asl_large_header);
578                         buffer = byte_stream_buffer + header_length;
579
580                         switch (resource_type) {
581                         case ACPI_RDESC_TYPE_LARGE_VENDOR:
582                                 /*
583                                  * Vendor Defined Resource:
584                                  * Add vendor data and ensure a 32-bit boundary for the structure
585                                  */
586                                 extra_struct_bytes =
587                                     ACPI_ROUND_UP_to_32_bITS(resource_length);
588                                 break;
589
590                         case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
591                         case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
592                                 /*
593                                  * 32-Bit or 16-bit Address Resource:
594                                  * Add the size of any optional data (resource_source)
595                                  */
596                                 extra_struct_bytes =
597                                     acpi_rs_stream_option_length
598                                     (resource_length,
599                                      resource_info->minimum_stream_size);
600                                 break;
601
602                         case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
603                                 /*
604                                  * Extended IRQ:
605                                  * Point past the interrupt_vector_flags to get the
606                                  * interrupt_table_length.
607                                  */
608                                 buffer++;
609
610                                 /*
611                                  * Add 4 bytes for each additional interrupt. Note: at least one
612                                  * interrupt is required and is included in the minimum
613                                  * descriptor size
614                                  */
615                                 extra_struct_bytes =
616                                     ((*buffer - 1) * sizeof(u32));
617
618                                 /* Add the size of any optional data (resource_source) */
619
620                                 extra_struct_bytes +=
621                                     acpi_rs_stream_option_length(resource_length
622                                                                  -
623                                                                  extra_struct_bytes,
624                                                                  resource_info->
625                                                                  minimum_stream_size);
626                                 break;
627
628                         case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
629                                 /*
630                                  * 64-Bit Address Resource:
631                                  * Add the size of any optional data (resource_source)
632                                  * Ensure a 64-bit boundary for the structure
633                                  */
634                                 extra_struct_bytes =
635                                     ACPI_ROUND_UP_to_64_bITS
636                                     (acpi_rs_stream_option_length
637                                      (resource_length,
638                                       resource_info->minimum_stream_size));
639                                 break;
640
641                         default:
642                                 break;
643                         }
644                 }
645
646                 /* Update the required buffer size for the internal descriptor structs */
647
648                 temp16 =
649                     (u16) (resource_info->minimum_struct_size +
650                            extra_struct_bytes);
651                 buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(temp16);
652
653                 /*
654                  * Update byte count and point to the next resource within the stream
655                  * using the size of the header plus the length contained in the header
656                  */
657                 temp16 = (u16) (header_length + resource_length);
658                 bytes_parsed += temp16;
659                 byte_stream_buffer += temp16;
660         }
661
662         /* This is the data the caller needs */
663
664         *size_needed = buffer_size;
665         return_ACPI_STATUS(AE_OK);
666 }
667
668 /*******************************************************************************
669  *
670  * FUNCTION:    acpi_rs_get_pci_routing_table_length
671  *
672  * PARAMETERS:  package_object          - Pointer to the package object
673  *              buffer_size_needed      - u32 pointer of the size buffer
674  *                                        needed to properly return the
675  *                                        parsed data
676  *
677  * RETURN:      Status
678  *
679  * DESCRIPTION: Given a package representing a PCI routing table, this
680  *              calculates the size of the corresponding linked list of
681  *              descriptions.
682  *
683  ******************************************************************************/
684
685 acpi_status
686 acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
687                                      acpi_size * buffer_size_needed)
688 {
689         u32 number_of_elements;
690         acpi_size temp_size_needed = 0;
691         union acpi_operand_object **top_object_list;
692         u32 index;
693         union acpi_operand_object *package_element;
694         union acpi_operand_object **sub_object_list;
695         u8 name_found;
696         u32 table_index;
697
698         ACPI_FUNCTION_TRACE("rs_get_pci_routing_table_length");
699
700         number_of_elements = package_object->package.count;
701
702         /*
703          * Calculate the size of the return buffer.
704          * The base size is the number of elements * the sizes of the
705          * structures.  Additional space for the strings is added below.
706          * The minus one is to subtract the size of the u8 Source[1]
707          * member because it is added below.
708          *
709          * But each PRT_ENTRY structure has a pointer to a string and
710          * the size of that string must be found.
711          */
712         top_object_list = package_object->package.elements;
713
714         for (index = 0; index < number_of_elements; index++) {
715                 /* Dereference the sub-package */
716
717                 package_element = *top_object_list;
718
719                 /*
720                  * The sub_object_list will now point to an array of the
721                  * four IRQ elements: Address, Pin, Source and source_index
722                  */
723                 sub_object_list = package_element->package.elements;
724
725                 /* Scan the irq_table_elements for the Source Name String */
726
727                 name_found = FALSE;
728
729                 for (table_index = 0; table_index < 4 && !name_found;
730                      table_index++) {
731                         if ((ACPI_TYPE_STRING ==
732                              ACPI_GET_OBJECT_TYPE(*sub_object_list))
733                             ||
734                             ((ACPI_TYPE_LOCAL_REFERENCE ==
735                               ACPI_GET_OBJECT_TYPE(*sub_object_list))
736                              && ((*sub_object_list)->reference.opcode ==
737                                  AML_INT_NAMEPATH_OP))) {
738                                 name_found = TRUE;
739                         } else {
740                                 /* Look at the next element */
741
742                                 sub_object_list++;
743                         }
744                 }
745
746                 temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
747
748                 /* Was a String type found? */
749
750                 if (name_found) {
751                         if (ACPI_GET_OBJECT_TYPE(*sub_object_list) ==
752                             ACPI_TYPE_STRING) {
753                                 /*
754                                  * The length String.Length field does not include the
755                                  * terminating NULL, add 1
756                                  */
757                                 temp_size_needed += ((acpi_size)
758                                                      (*sub_object_list)->string.
759                                                      length + 1);
760                         } else {
761                                 temp_size_needed +=
762                                     acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
763                         }
764                 } else {
765                         /*
766                          * If no name was found, then this is a NULL, which is
767                          * translated as a u32 zero.
768                          */
769                         temp_size_needed += sizeof(u32);
770                 }
771
772                 /* Round up the size since each element must be aligned */
773
774                 temp_size_needed = ACPI_ROUND_UP_to_64_bITS(temp_size_needed);
775
776                 /* Point to the next union acpi_operand_object */
777
778                 top_object_list++;
779         }
780
781         /*
782          * Adding an extra element to the end of the list, essentially a
783          * NULL terminator
784          */
785         *buffer_size_needed =
786             temp_size_needed + sizeof(struct acpi_pci_routing_table);
787         return_ACPI_STATUS(AE_OK);
788 }