xref: /dflybsd-src/sys/contrib/dev/acpica/source/components/resources/rscalc.c (revision c8860c9adc386d4c6e42a14b22ea4165d1f37b72)
1  /*******************************************************************************
2   *
3   * Module Name: rscalc - Calculate stream and list lengths
4   *
5   ******************************************************************************/
6  
7  /******************************************************************************
8   *
9   * 1. Copyright Notice
10   *
11   * Some or all of this work - Copyright (c) 1999 - 2021, Intel Corp.
12   * All rights reserved.
13   *
14   * 2. License
15   *
16   * 2.1. This is your license from Intel Corp. under its intellectual property
17   * rights. You may have additional license terms from the party that provided
18   * you this software, covering your right to use that party's intellectual
19   * property rights.
20   *
21   * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22   * copy of the source code appearing in this file ("Covered Code") an
23   * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24   * base code distributed originally by Intel ("Original Intel Code") to copy,
25   * make derivatives, distribute, use and display any portion of the Covered
26   * Code in any form, with the right to sublicense such rights; and
27   *
28   * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29   * license (with the right to sublicense), under only those claims of Intel
30   * patents that are infringed by the Original Intel Code, to make, use, sell,
31   * offer to sell, and import the Covered Code and derivative works thereof
32   * solely to the minimum extent necessary to exercise the above copyright
33   * license, and in no event shall the patent license extend to any additions
34   * to or modifications of the Original Intel Code. No other license or right
35   * is granted directly or by implication, estoppel or otherwise;
36   *
37   * The above copyright and patent license is granted only if the following
38   * conditions are met:
39   *
40   * 3. Conditions
41   *
42   * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43   * Redistribution of source code of any substantial portion of the Covered
44   * Code or modification with rights to further distribute source must include
45   * the above Copyright Notice, the above License, this list of Conditions,
46   * and the following Disclaimer and Export Compliance provision. In addition,
47   * Licensee must cause all Covered Code to which Licensee contributes to
48   * contain a file documenting the changes Licensee made to create that Covered
49   * Code and the date of any change. Licensee must include in that file the
50   * documentation of any changes made by any predecessor Licensee. Licensee
51   * must include a prominent statement that the modification is derived,
52   * directly or indirectly, from Original Intel Code.
53   *
54   * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55   * Redistribution of source code of any substantial portion of the Covered
56   * Code or modification without rights to further distribute source must
57   * include the following Disclaimer and Export Compliance provision in the
58   * documentation and/or other materials provided with distribution. In
59   * addition, Licensee may not authorize further sublicense of source of any
60   * portion of the Covered Code, and must include terms to the effect that the
61   * license from Licensee to its licensee is limited to the intellectual
62   * property embodied in the software Licensee provides to its licensee, and
63   * not to intellectual property embodied in modifications its licensee may
64   * make.
65   *
66   * 3.3. Redistribution of Executable. Redistribution in executable form of any
67   * substantial portion of the Covered Code or modification must reproduce the
68   * above Copyright Notice, and the following Disclaimer and Export Compliance
69   * provision in the documentation and/or other materials provided with the
70   * distribution.
71   *
72   * 3.4. Intel retains all right, title, and interest in and to the Original
73   * Intel Code.
74   *
75   * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76   * Intel shall be used in advertising or otherwise to promote the sale, use or
77   * other dealings in products derived from or relating to the Covered Code
78   * without prior written authorization from Intel.
79   *
80   * 4. Disclaimer and Export Compliance
81   *
82   * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83   * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84   * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85   * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86   * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87   * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88   * PARTICULAR PURPOSE.
89   *
90   * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91   * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92   * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93   * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94   * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95   * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96   * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97   * LIMITED REMEDY.
98   *
99   * 4.3. Licensee shall not export, either directly or indirectly, any of this
100   * software or system incorporating such software without first obtaining any
101   * required license or other approval from the U. S. Department of Commerce or
102   * any other agency or department of the United States Government. In the
103   * event Licensee exports any such software from the United States or
104   * re-exports any such software from a foreign destination, Licensee shall
105   * ensure that the distribution and export/re-export of the software is in
106   * compliance with all laws, regulations, orders, or other restrictions of the
107   * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108   * any of its subsidiaries will export/re-export any technical data, process,
109   * software, or service, directly or indirectly, to any country for which the
110   * United States government or any agency thereof requires an export license,
111   * other governmental approval, or letter of assurance, without first obtaining
112   * such license, approval or letter.
113   *
114   *****************************************************************************
115   *
116   * Alternatively, you may choose to be licensed under the terms of the
117   * following license:
118   *
119   * Redistribution and use in source and binary forms, with or without
120   * modification, are permitted provided that the following conditions
121   * are met:
122   * 1. Redistributions of source code must retain the above copyright
123   *    notice, this list of conditions, and the following disclaimer,
124   *    without modification.
125   * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126   *    substantially similar to the "NO WARRANTY" disclaimer below
127   *    ("Disclaimer") and any redistribution must be conditioned upon
128   *    including a substantially similar Disclaimer requirement for further
129   *    binary redistribution.
130   * 3. Neither the names of the above-listed copyright holders nor the names
131   *    of any contributors may be used to endorse or promote products derived
132   *    from this software without specific prior written permission.
133   *
134   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145   *
146   * Alternatively, you may choose to be licensed under the terms of the
147   * GNU General Public License ("GPL") version 2 as published by the Free
148   * Software Foundation.
149   *
150   *****************************************************************************/
151  
152  #include "acpi.h"
153  #include "accommon.h"
154  #include "acresrc.h"
155  #include "acnamesp.h"
156  
157  
158  #define _COMPONENT          ACPI_RESOURCES
159          ACPI_MODULE_NAME    ("rscalc")
160  
161  
162  /* Local prototypes */
163  
164  static UINT8
165  AcpiRsCountSetBits (
166      UINT16                  BitField);
167  
168  static ACPI_RS_LENGTH
169  AcpiRsStructOptionLength (
170      ACPI_RESOURCE_SOURCE    *ResourceSource);
171  
172  static UINT32
173  AcpiRsStreamOptionLength (
174      UINT32                  ResourceLength,
175      UINT32                  MinimumTotalLength);
176  
177  
178  /*******************************************************************************
179   *
180   * FUNCTION:    AcpiRsCountSetBits
181   *
182   * PARAMETERS:  BitField        - Field in which to count bits
183   *
184   * RETURN:      Number of bits set within the field
185   *
186   * DESCRIPTION: Count the number of bits set in a resource field. Used for
187   *              (Short descriptor) interrupt and DMA lists.
188   *
189   ******************************************************************************/
190  
191  static UINT8
192  AcpiRsCountSetBits (
193      UINT16                  BitField)
194  {
195      UINT8                   BitsSet;
196  
197  
198      ACPI_FUNCTION_ENTRY ();
199  
200  
201      for (BitsSet = 0; BitField; BitsSet++)
202      {
203          /* Zero the least significant bit that is set */
204  
205          BitField &= (UINT16) (BitField - 1);
206      }
207  
208      return (BitsSet);
209  }
210  
211  
212  /*******************************************************************************
213   *
214   * FUNCTION:    AcpiRsStructOptionLength
215   *
216   * PARAMETERS:  ResourceSource      - Pointer to optional descriptor field
217   *
218   * RETURN:      Status
219   *
220   * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
221   *              ResourceSource fields in some Large descriptors. Used during
222   *              list-to-stream conversion
223   *
224   ******************************************************************************/
225  
226  static ACPI_RS_LENGTH
227  AcpiRsStructOptionLength (
228      ACPI_RESOURCE_SOURCE    *ResourceSource)
229  {
230      ACPI_FUNCTION_ENTRY ();
231  
232  
233      /*
234       * If the ResourceSource string is valid, return the size of the string
235       * (StringLength includes the NULL terminator) plus the size of the
236       * ResourceSourceIndex (1).
237       */
238      if (ResourceSource->StringPtr)
239      {
240          return ((ACPI_RS_LENGTH) (ResourceSource->StringLength + 1));
241      }
242  
243      return (0);
244  }
245  
246  
247  /*******************************************************************************
248   *
249   * FUNCTION:    AcpiRsStreamOptionLength
250   *
251   * PARAMETERS:  ResourceLength      - Length from the resource header
252   *              MinimumTotalLength  - Minimum length of this resource, before
253   *                                    any optional fields. Includes header size
254   *
255   * RETURN:      Length of optional string (0 if no string present)
256   *
257   * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
258   *              ResourceSource fields in some Large descriptors. Used during
259   *              stream-to-list conversion
260   *
261   ******************************************************************************/
262  
263  static UINT32
264  AcpiRsStreamOptionLength (
265      UINT32                  ResourceLength,
266      UINT32                  MinimumAmlResourceLength)
267  {
268      UINT32                  StringLength = 0;
269  
270  
271      ACPI_FUNCTION_ENTRY ();
272  
273  
274      /*
275       * The ResourceSourceIndex and ResourceSource are optional elements of
276       * some Large-type resource descriptors.
277       */
278  
279      /*
280       * If the length of the actual resource descriptor is greater than the
281       * ACPI spec-defined minimum length, it means that a ResourceSourceIndex
282       * exists and is followed by a (required) null terminated string. The
283       * string length (including the null terminator) is the resource length
284       * minus the minimum length, minus one byte for the ResourceSourceIndex
285       * itself.
286       */
287      if (ResourceLength > MinimumAmlResourceLength)
288      {
289          /* Compute the length of the optional string */
290  
291          StringLength = ResourceLength - MinimumAmlResourceLength - 1;
292      }
293  
294      /*
295       * Round the length up to a multiple of the native word in order to
296       * guarantee that the entire resource descriptor is native word aligned
297       */
298      return ((UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (StringLength));
299  }
300  
301  
302  /*******************************************************************************
303   *
304   * FUNCTION:    AcpiRsGetAmlLength
305   *
306   * PARAMETERS:  Resource            - Pointer to the resource linked list
307   *              ResourceListSize    - Size of the resource linked list
308   *              SizeNeeded          - Where the required size is returned
309   *
310   * RETURN:      Status
311   *
312   * DESCRIPTION: Takes a linked list of internal resource descriptors and
313   *              calculates the size buffer needed to hold the corresponding
314   *              external resource byte stream.
315   *
316   ******************************************************************************/
317  
318  ACPI_STATUS
319  AcpiRsGetAmlLength (
320      ACPI_RESOURCE           *Resource,
321      ACPI_SIZE               ResourceListSize,
322      ACPI_SIZE               *SizeNeeded)
323  {
324      ACPI_SIZE               AmlSizeNeeded = 0;
325      ACPI_RESOURCE           *ResourceEnd;
326      ACPI_RS_LENGTH          TotalSize;
327  
328  
329      ACPI_FUNCTION_TRACE (RsGetAmlLength);
330  
331  
332      /* Traverse entire list of internal resource descriptors */
333  
334      ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, ResourceListSize);
335      while (Resource < ResourceEnd)
336      {
337          /* Validate the descriptor type */
338  
339          if (Resource->Type > ACPI_RESOURCE_TYPE_MAX)
340          {
341              return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
342          }
343  
344          /* Sanity check the length. It must not be zero, or we loop forever */
345  
346          if (!Resource->Length)
347          {
348              return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
349          }
350  
351          /* Get the base size of the (external stream) resource descriptor */
352  
353          TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type];
354  
355          /*
356           * Augment the base size for descriptors with optional and/or
357           * variable-length fields
358           */
359          switch (Resource->Type)
360          {
361          case ACPI_RESOURCE_TYPE_IRQ:
362  
363              /* Length can be 3 or 2 */
364  
365              if (Resource->Data.Irq.DescriptorLength == 2)
366              {
367                  TotalSize--;
368              }
369              break;
370  
371  
372          case ACPI_RESOURCE_TYPE_START_DEPENDENT:
373  
374              /* Length can be 1 or 0 */
375  
376              if (Resource->Data.Irq.DescriptorLength == 0)
377              {
378                  TotalSize--;
379              }
380              break;
381  
382  
383          case ACPI_RESOURCE_TYPE_VENDOR:
384              /*
385               * Vendor Defined Resource:
386               * For a Vendor Specific resource, if the Length is between 1 and 7
387               * it will be created as a Small Resource data type, otherwise it
388               * is a Large Resource data type.
389               */
390              if (Resource->Data.Vendor.ByteLength > 7)
391              {
392                  /* Base size of a Large resource descriptor */
393  
394                  TotalSize = sizeof (AML_RESOURCE_LARGE_HEADER);
395              }
396  
397              /* Add the size of the vendor-specific data */
398  
399              TotalSize = (ACPI_RS_LENGTH)
400                  (TotalSize + Resource->Data.Vendor.ByteLength);
401              break;
402  
403  
404          case ACPI_RESOURCE_TYPE_END_TAG:
405              /*
406               * End Tag:
407               * We are done -- return the accumulated total size.
408               */
409              *SizeNeeded = AmlSizeNeeded + TotalSize;
410  
411              /* Normal exit */
412  
413              return_ACPI_STATUS (AE_OK);
414  
415  
416          case ACPI_RESOURCE_TYPE_ADDRESS16:
417              /*
418               * 16-Bit Address Resource:
419               * Add the size of the optional ResourceSource info
420               */
421              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
422                  AcpiRsStructOptionLength (
423                      &Resource->Data.Address16.ResourceSource));
424              break;
425  
426  
427          case ACPI_RESOURCE_TYPE_ADDRESS32:
428              /*
429               * 32-Bit Address Resource:
430               * Add the size of the optional ResourceSource info
431               */
432              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
433                  AcpiRsStructOptionLength (
434                      &Resource->Data.Address32.ResourceSource));
435              break;
436  
437  
438          case ACPI_RESOURCE_TYPE_ADDRESS64:
439              /*
440               * 64-Bit Address Resource:
441               * Add the size of the optional ResourceSource info
442               */
443              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
444                  AcpiRsStructOptionLength (
445                      &Resource->Data.Address64.ResourceSource));
446              break;
447  
448  
449          case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
450              /*
451               * Extended IRQ Resource:
452               * Add the size of each additional optional interrupt beyond the
453               * required 1 (4 bytes for each UINT32 interrupt number)
454               */
455              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
456                  ((Resource->Data.ExtendedIrq.InterruptCount - 1) * 4) +
457  
458                  /* Add the size of the optional ResourceSource info */
459  
460                  AcpiRsStructOptionLength (
461                      &Resource->Data.ExtendedIrq.ResourceSource));
462              break;
463  
464  
465          case ACPI_RESOURCE_TYPE_GPIO:
466  
467              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
468                  (Resource->Data.Gpio.PinTableLength * 2) +
469                  Resource->Data.Gpio.ResourceSource.StringLength +
470                  Resource->Data.Gpio.VendorLength);
471  
472              break;
473  
474          case ACPI_RESOURCE_TYPE_PIN_FUNCTION:
475  
476              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
477                  (Resource->Data.PinFunction.PinTableLength * 2) +
478                  Resource->Data.PinFunction.ResourceSource.StringLength +
479                  Resource->Data.PinFunction.VendorLength);
480  
481              break;
482  
483  
484          case ACPI_RESOURCE_TYPE_SERIAL_BUS:
485  
486              TotalSize = AcpiGbl_AmlResourceSerialBusSizes [
487                  Resource->Data.CommonSerialBus.Type];
488  
489              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
490                  Resource->Data.I2cSerialBus.ResourceSource.StringLength +
491                  Resource->Data.I2cSerialBus.VendorLength);
492  
493              break;
494  
495          case ACPI_RESOURCE_TYPE_PIN_CONFIG:
496  
497              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
498                  (Resource->Data.PinConfig.PinTableLength * 2) +
499                  Resource->Data.PinConfig.ResourceSource.StringLength +
500                  Resource->Data.PinConfig.VendorLength);
501  
502              break;
503  
504          case ACPI_RESOURCE_TYPE_PIN_GROUP:
505  
506              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
507                  (Resource->Data.PinGroup.PinTableLength * 2) +
508                  Resource->Data.PinGroup.ResourceLabel.StringLength +
509                  Resource->Data.PinGroup.VendorLength);
510  
511              break;
512  
513          case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION:
514  
515              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
516                  Resource->Data.PinGroupFunction.ResourceSource.StringLength +
517                  Resource->Data.PinGroupFunction.ResourceSourceLabel.StringLength +
518                  Resource->Data.PinGroupFunction.VendorLength);
519  
520              break;
521  
522          case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG:
523  
524              TotalSize = (ACPI_RS_LENGTH) (TotalSize +
525                  Resource->Data.PinGroupConfig.ResourceSource.StringLength +
526                  Resource->Data.PinGroupConfig.ResourceSourceLabel.StringLength +
527                  Resource->Data.PinGroupConfig.VendorLength);
528  
529              break;
530  
531          default:
532  
533              break;
534          }
535  
536          /* Update the total */
537  
538          AmlSizeNeeded += TotalSize;
539  
540          /* Point to the next object */
541  
542          Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length);
543      }
544  
545      /* Did not find an EndTag resource descriptor */
546  
547      return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
548  }
549  
550  
551  /*******************************************************************************
552   *
553   * FUNCTION:    AcpiRsGetListLength
554   *
555   * PARAMETERS:  AmlBuffer           - Pointer to the resource byte stream
556   *              AmlBufferLength     - Size of AmlBuffer
557   *              SizeNeeded          - Where the size needed is returned
558   *
559   * RETURN:      Status
560   *
561   * DESCRIPTION: Takes an external resource byte stream and calculates the size
562   *              buffer needed to hold the corresponding internal resource
563   *              descriptor linked list.
564   *
565   ******************************************************************************/
566  
567  ACPI_STATUS
568  AcpiRsGetListLength (
569      UINT8                   *AmlBuffer,
570      UINT32                  AmlBufferLength,
571      ACPI_SIZE               *SizeNeeded)
572  {
573      ACPI_STATUS             Status;
574      UINT8                   *EndAml;
575      UINT8                   *Buffer;
576      UINT32                  BufferSize;
577      UINT16                  Temp16;
578      UINT16                  ResourceLength;
579      UINT32                  ExtraStructBytes;
580      UINT8                   ResourceIndex;
581      UINT8                   MinimumAmlResourceLength;
582      AML_RESOURCE            *AmlResource;
583  
584  
585      ACPI_FUNCTION_TRACE (RsGetListLength);
586  
587  
588      *SizeNeeded = ACPI_RS_SIZE_MIN;         /* Minimum size is one EndTag */
589      EndAml = AmlBuffer + AmlBufferLength;
590  
591      /* Walk the list of AML resource descriptors */
592  
593      while (AmlBuffer < EndAml)
594      {
595          /* Validate the Resource Type and Resource Length */
596  
597          Status = AcpiUtValidateResource (NULL, AmlBuffer, &ResourceIndex);
598          if (ACPI_FAILURE (Status))
599          {
600              /*
601               * Exit on failure. Cannot continue because the descriptor length
602               * may be bogus also.
603               */
604              return_ACPI_STATUS (Status);
605          }
606  
607          AmlResource = (void *) AmlBuffer;
608  
609          /* Get the resource length and base (minimum) AML size */
610  
611          ResourceLength = AcpiUtGetResourceLength (AmlBuffer);
612          MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
613  
614          /*
615           * Augment the size for descriptors with optional
616           * and/or variable length fields
617           */
618          ExtraStructBytes = 0;
619          Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer);
620  
621          switch (AcpiUtGetResourceType (AmlBuffer))
622          {
623          case ACPI_RESOURCE_NAME_IRQ:
624              /*
625               * IRQ Resource:
626               * Get the number of bits set in the 16-bit IRQ mask
627               */
628              ACPI_MOVE_16_TO_16 (&Temp16, Buffer);
629              ExtraStructBytes = AcpiRsCountSetBits (Temp16);
630              break;
631  
632  
633          case ACPI_RESOURCE_NAME_DMA:
634              /*
635               * DMA Resource:
636               * Get the number of bits set in the 8-bit DMA mask
637               */
638              ExtraStructBytes = AcpiRsCountSetBits (*Buffer);
639              break;
640  
641  
642          case ACPI_RESOURCE_NAME_VENDOR_SMALL:
643          case ACPI_RESOURCE_NAME_VENDOR_LARGE:
644              /*
645               * Vendor Resource:
646               * Get the number of vendor data bytes
647               */
648              ExtraStructBytes = ResourceLength;
649  
650              /*
651               * There is already one byte included in the minimum
652               * descriptor size. If there are extra struct bytes,
653               * subtract one from the count.
654               */
655              if (ExtraStructBytes)
656              {
657                  ExtraStructBytes--;
658              }
659              break;
660  
661  
662          case ACPI_RESOURCE_NAME_END_TAG:
663              /*
664               * End Tag: This is the normal exit
665               */
666              return_ACPI_STATUS (AE_OK);
667  
668  
669          case ACPI_RESOURCE_NAME_ADDRESS32:
670          case ACPI_RESOURCE_NAME_ADDRESS16:
671          case ACPI_RESOURCE_NAME_ADDRESS64:
672              /*
673               * Address Resource:
674               * Add the size of the optional ResourceSource
675               */
676              ExtraStructBytes = AcpiRsStreamOptionLength (
677                  ResourceLength, MinimumAmlResourceLength);
678              break;
679  
680  
681          case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
682              /*
683               * Extended IRQ Resource:
684               * Using the InterruptTableLength, add 4 bytes for each additional
685               * interrupt. Note: at least one interrupt is required and is
686               * included in the minimum descriptor size (reason for the -1)
687               */
688              ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32);
689  
690              /* Add the size of the optional ResourceSource */
691  
692              ExtraStructBytes += AcpiRsStreamOptionLength (
693                  ResourceLength - ExtraStructBytes, MinimumAmlResourceLength);
694              break;
695  
696          case ACPI_RESOURCE_NAME_GPIO:
697  
698              /* Vendor data is optional */
699  
700              if (AmlResource->Gpio.VendorLength)
701              {
702                  ExtraStructBytes +=
703                      AmlResource->Gpio.VendorOffset -
704                      AmlResource->Gpio.PinTableOffset +
705                      AmlResource->Gpio.VendorLength;
706              }
707              else
708              {
709                  ExtraStructBytes +=
710                      AmlResource->LargeHeader.ResourceLength +
711                      sizeof (AML_RESOURCE_LARGE_HEADER) -
712                      AmlResource->Gpio.PinTableOffset;
713              }
714              break;
715  
716          case ACPI_RESOURCE_NAME_PIN_FUNCTION:
717  
718              /* Vendor data is optional */
719  
720              if (AmlResource->PinFunction.VendorLength)
721              {
722                  ExtraStructBytes +=
723                      AmlResource->PinFunction.VendorOffset -
724                      AmlResource->PinFunction.PinTableOffset +
725                      AmlResource->PinFunction.VendorLength;
726              }
727              else
728              {
729                  ExtraStructBytes +=
730                      AmlResource->LargeHeader.ResourceLength +
731                      sizeof (AML_RESOURCE_LARGE_HEADER) -
732                      AmlResource->PinFunction.PinTableOffset;
733              }
734              break;
735  
736          case ACPI_RESOURCE_NAME_SERIAL_BUS:
737  
738              MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[
739                  AmlResource->CommonSerialBus.Type];
740              ExtraStructBytes +=
741                  AmlResource->CommonSerialBus.ResourceLength -
742                  MinimumAmlResourceLength;
743              break;
744  
745          case ACPI_RESOURCE_NAME_PIN_CONFIG:
746  
747              /* Vendor data is optional */
748  
749              if (AmlResource->PinConfig.VendorLength)
750              {
751                  ExtraStructBytes +=
752                      AmlResource->PinConfig.VendorOffset -
753                      AmlResource->PinConfig.PinTableOffset +
754                      AmlResource->PinConfig.VendorLength;
755              }
756              else
757              {
758                  ExtraStructBytes +=
759                      AmlResource->LargeHeader.ResourceLength +
760                      sizeof (AML_RESOURCE_LARGE_HEADER) -
761                      AmlResource->PinConfig.PinTableOffset;
762              }
763              break;
764  
765          case ACPI_RESOURCE_NAME_PIN_GROUP:
766  
767              ExtraStructBytes +=
768                  AmlResource->PinGroup.VendorOffset -
769                  AmlResource->PinGroup.PinTableOffset +
770                  AmlResource->PinGroup.VendorLength;
771  
772              break;
773  
774          case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION:
775  
776              ExtraStructBytes +=
777                  AmlResource->PinGroupFunction.VendorOffset -
778                  AmlResource->PinGroupFunction.ResSourceOffset +
779                  AmlResource->PinGroupFunction.VendorLength;
780  
781              break;
782  
783          case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG:
784  
785              ExtraStructBytes +=
786                  AmlResource->PinGroupConfig.VendorOffset -
787                  AmlResource->PinGroupConfig.ResSourceOffset +
788                  AmlResource->PinGroupConfig.VendorLength;
789  
790              break;
791  
792          default:
793  
794              break;
795          }
796  
797          /*
798           * Update the required buffer size for the internal descriptor structs
799           *
800           * Important: Round the size up for the appropriate alignment. This
801           * is a requirement on IA64.
802           */
803          if (AcpiUtGetResourceType (AmlBuffer) ==
804              ACPI_RESOURCE_NAME_SERIAL_BUS)
805          {
806              BufferSize = AcpiGbl_ResourceStructSerialBusSizes[
807                  AmlResource->CommonSerialBus.Type] + ExtraStructBytes;
808          }
809          else
810          {
811              BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] +
812                  ExtraStructBytes;
813          }
814  
815          BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize);
816          *SizeNeeded += BufferSize;
817  
818          ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES,
819              "Type %.2X, AmlLength %.2X InternalLength %.2X%8X\n",
820              AcpiUtGetResourceType (AmlBuffer),
821              AcpiUtGetDescriptorLength (AmlBuffer), ACPI_FORMAT_UINT64(*SizeNeeded)));
822  
823          /*
824           * Point to the next resource within the AML stream using the length
825           * contained in the resource descriptor header
826           */
827          AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer);
828      }
829  
830      /* Did not find an EndTag resource descriptor */
831  
832      return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
833  }
834  
835  
836  /*******************************************************************************
837   *
838   * FUNCTION:    AcpiRsGetPciRoutingTableLength
839   *
840   * PARAMETERS:  PackageObject           - Pointer to the package object
841   *              BufferSizeNeeded        - UINT32 pointer of the size buffer
842   *                                        needed to properly return the
843   *                                        parsed data
844   *
845   * RETURN:      Status
846   *
847   * DESCRIPTION: Given a package representing a PCI routing table, this
848   *              calculates the size of the corresponding linked list of
849   *              descriptions.
850   *
851   ******************************************************************************/
852  
853  ACPI_STATUS
854  AcpiRsGetPciRoutingTableLength (
855      ACPI_OPERAND_OBJECT     *PackageObject,
856      ACPI_SIZE               *BufferSizeNeeded)
857  {
858      UINT32                  NumberOfElements;
859      ACPI_SIZE               TempSizeNeeded = 0;
860      ACPI_OPERAND_OBJECT     **TopObjectList;
861      UINT32                  Index;
862      ACPI_OPERAND_OBJECT     *PackageElement;
863      ACPI_OPERAND_OBJECT     **SubObjectList;
864      BOOLEAN                 NameFound;
865      UINT32                  TableIndex;
866  
867  
868      ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength);
869  
870  
871      NumberOfElements = PackageObject->Package.Count;
872  
873      /*
874       * Calculate the size of the return buffer.
875       * The base size is the number of elements * the sizes of the
876       * structures. Additional space for the strings is added below.
877       * The minus one is to subtract the size of the UINT8 Source[1]
878       * member because it is added below.
879       *
880       * But each PRT_ENTRY structure has a pointer to a string and
881       * the size of that string must be found.
882       */
883      TopObjectList = PackageObject->Package.Elements;
884  
885      for (Index = 0; Index < NumberOfElements; Index++)
886      {
887          /* Dereference the subpackage */
888  
889          PackageElement = *TopObjectList;
890  
891          /* We must have a valid Package object */
892  
893          if (!PackageElement ||
894              (PackageElement->Common.Type != ACPI_TYPE_PACKAGE))
895          {
896              return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
897          }
898  
899          /*
900           * The SubObjectList will now point to an array of the
901           * four IRQ elements: Address, Pin, Source and SourceIndex
902           */
903          SubObjectList = PackageElement->Package.Elements;
904  
905          /* Scan the IrqTableElements for the Source Name String */
906  
907          NameFound = FALSE;
908  
909          for (TableIndex = 0;
910               TableIndex < PackageElement->Package.Count && !NameFound;
911               TableIndex++)
912          {
913              if (*SubObjectList && /* Null object allowed */
914  
915                  ((ACPI_TYPE_STRING ==
916                      (*SubObjectList)->Common.Type) ||
917  
918                  ((ACPI_TYPE_LOCAL_REFERENCE ==
919                      (*SubObjectList)->Common.Type) &&
920  
921                      ((*SubObjectList)->Reference.Class ==
922                          ACPI_REFCLASS_NAME))))
923              {
924                  NameFound = TRUE;
925              }
926              else
927              {
928                  /* Look at the next element */
929  
930                  SubObjectList++;
931              }
932          }
933  
934          TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);
935  
936          /* Was a String type found? */
937  
938          if (NameFound)
939          {
940              if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING)
941              {
942                  /*
943                   * The length String.Length field does not include the
944                   * terminating NULL, add 1
945                   */
946                  TempSizeNeeded += ((ACPI_SIZE)
947                      (*SubObjectList)->String.Length + 1);
948              }
949              else
950              {
951                  TempSizeNeeded += AcpiNsGetPathnameLength (
952                      (*SubObjectList)->Reference.Node);
953              }
954          }
955          else
956          {
957              /*
958               * If no name was found, then this is a NULL, which is
959               * translated as a UINT32 zero.
960               */
961              TempSizeNeeded += sizeof (UINT32);
962          }
963  
964          /* Round up the size since each element must be aligned */
965  
966          TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded);
967  
968          /* Point to the next ACPI_OPERAND_OBJECT */
969  
970          TopObjectList++;
971      }
972  
973      /*
974       * Add an extra element to the end of the list, essentially a
975       * NULL terminator
976       */
977      *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE);
978      return_ACPI_STATUS (AE_OK);
979  }
980