1ae115bc7Smrj /*******************************************************************************
2ae115bc7Smrj *
3ae115bc7Smrj * Module Name: rscalc - Calculate stream and list lengths
4ae115bc7Smrj *
5ae115bc7Smrj ******************************************************************************/
6ae115bc7Smrj
726f3cdf0SGordon Ross /*
8*cb565728SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp.
9ae115bc7Smrj * All rights reserved.
10ae115bc7Smrj *
1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross * are met:
1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross * without modification.
1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross * binary redistribution.
2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross * from this software without specific prior written permission.
25ae115bc7Smrj *
2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross * Software Foundation.
29ae115bc7Smrj *
3026f3cdf0SGordon Ross * NO WARRANTY
3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross */
43ae115bc7Smrj
44ae115bc7Smrj #include "acpi.h"
45aa2aa9a6SDana Myers #include "accommon.h"
46ae115bc7Smrj #include "acresrc.h"
47ae115bc7Smrj #include "acnamesp.h"
48ae115bc7Smrj
49db2bae30SDana Myers
50ae115bc7Smrj #define _COMPONENT ACPI_RESOURCES
51ae115bc7Smrj ACPI_MODULE_NAME ("rscalc")
52ae115bc7Smrj
53ae115bc7Smrj
54ae115bc7Smrj /* Local prototypes */
55ae115bc7Smrj
56ae115bc7Smrj static UINT8
57ae115bc7Smrj AcpiRsCountSetBits (
58ae115bc7Smrj UINT16 BitField);
59ae115bc7Smrj
60ae115bc7Smrj static ACPI_RS_LENGTH
61ae115bc7Smrj AcpiRsStructOptionLength (
62ae115bc7Smrj ACPI_RESOURCE_SOURCE *ResourceSource);
63ae115bc7Smrj
64ae115bc7Smrj static UINT32
65ae115bc7Smrj AcpiRsStreamOptionLength (
66ae115bc7Smrj UINT32 ResourceLength,
67ae115bc7Smrj UINT32 MinimumTotalLength);
68ae115bc7Smrj
69ae115bc7Smrj
70ae115bc7Smrj /*******************************************************************************
71ae115bc7Smrj *
72ae115bc7Smrj * FUNCTION: AcpiRsCountSetBits
73ae115bc7Smrj *
74ae115bc7Smrj * PARAMETERS: BitField - Field in which to count bits
75ae115bc7Smrj *
76ae115bc7Smrj * RETURN: Number of bits set within the field
77ae115bc7Smrj *
78ae115bc7Smrj * DESCRIPTION: Count the number of bits set in a resource field. Used for
79ae115bc7Smrj * (Short descriptor) interrupt and DMA lists.
80ae115bc7Smrj *
81ae115bc7Smrj ******************************************************************************/
82ae115bc7Smrj
83ae115bc7Smrj static UINT8
AcpiRsCountSetBits(UINT16 BitField)84ae115bc7Smrj AcpiRsCountSetBits (
85ae115bc7Smrj UINT16 BitField)
86ae115bc7Smrj {
87ae115bc7Smrj UINT8 BitsSet;
88ae115bc7Smrj
89ae115bc7Smrj
90ae115bc7Smrj ACPI_FUNCTION_ENTRY ();
91ae115bc7Smrj
92ae115bc7Smrj
93ae115bc7Smrj for (BitsSet = 0; BitField; BitsSet++)
94ae115bc7Smrj {
95ae115bc7Smrj /* Zero the least significant bit that is set */
96ae115bc7Smrj
97db2bae30SDana Myers BitField &= (UINT16) (BitField - 1);
98ae115bc7Smrj }
99ae115bc7Smrj
100ae115bc7Smrj return (BitsSet);
101ae115bc7Smrj }
102ae115bc7Smrj
103ae115bc7Smrj
104ae115bc7Smrj /*******************************************************************************
105ae115bc7Smrj *
106ae115bc7Smrj * FUNCTION: AcpiRsStructOptionLength
107ae115bc7Smrj *
108ae115bc7Smrj * PARAMETERS: ResourceSource - Pointer to optional descriptor field
109ae115bc7Smrj *
110ae115bc7Smrj * RETURN: Status
111ae115bc7Smrj *
112ae115bc7Smrj * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
113ae115bc7Smrj * ResourceSource fields in some Large descriptors. Used during
114ae115bc7Smrj * list-to-stream conversion
115ae115bc7Smrj *
116ae115bc7Smrj ******************************************************************************/
117ae115bc7Smrj
118ae115bc7Smrj static ACPI_RS_LENGTH
AcpiRsStructOptionLength(ACPI_RESOURCE_SOURCE * ResourceSource)119ae115bc7Smrj AcpiRsStructOptionLength (
120ae115bc7Smrj ACPI_RESOURCE_SOURCE *ResourceSource)
121ae115bc7Smrj {
122ae115bc7Smrj ACPI_FUNCTION_ENTRY ();
123ae115bc7Smrj
124ae115bc7Smrj
125ae115bc7Smrj /*
126ae115bc7Smrj * If the ResourceSource string is valid, return the size of the string
127ae115bc7Smrj * (StringLength includes the NULL terminator) plus the size of the
128ae115bc7Smrj * ResourceSourceIndex (1).
129ae115bc7Smrj */
130ae115bc7Smrj if (ResourceSource->StringPtr)
131ae115bc7Smrj {
132ae115bc7Smrj return ((ACPI_RS_LENGTH) (ResourceSource->StringLength + 1));
133ae115bc7Smrj }
134ae115bc7Smrj
135ae115bc7Smrj return (0);
136ae115bc7Smrj }
137ae115bc7Smrj
138ae115bc7Smrj
139ae115bc7Smrj /*******************************************************************************
140ae115bc7Smrj *
141ae115bc7Smrj * FUNCTION: AcpiRsStreamOptionLength
142ae115bc7Smrj *
143ae115bc7Smrj * PARAMETERS: ResourceLength - Length from the resource header
144ae115bc7Smrj * MinimumTotalLength - Minimum length of this resource, before
145ae115bc7Smrj * any optional fields. Includes header size
146ae115bc7Smrj *
147ae115bc7Smrj * RETURN: Length of optional string (0 if no string present)
148ae115bc7Smrj *
149ae115bc7Smrj * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
150ae115bc7Smrj * ResourceSource fields in some Large descriptors. Used during
151ae115bc7Smrj * stream-to-list conversion
152ae115bc7Smrj *
153ae115bc7Smrj ******************************************************************************/
154ae115bc7Smrj
155ae115bc7Smrj static UINT32
AcpiRsStreamOptionLength(UINT32 ResourceLength,UINT32 MinimumAmlResourceLength)156ae115bc7Smrj AcpiRsStreamOptionLength (
157ae115bc7Smrj UINT32 ResourceLength,
158ae115bc7Smrj UINT32 MinimumAmlResourceLength)
159ae115bc7Smrj {
160ae115bc7Smrj UINT32 StringLength = 0;
161ae115bc7Smrj
162ae115bc7Smrj
163ae115bc7Smrj ACPI_FUNCTION_ENTRY ();
164ae115bc7Smrj
165ae115bc7Smrj
166ae115bc7Smrj /*
167*cb565728SJerry Jelinek * The ResourceSourceIndex and ResourceSource are optional elements of
168*cb565728SJerry Jelinek * some Large-type resource descriptors.
169ae115bc7Smrj */
170ae115bc7Smrj
171ae115bc7Smrj /*
172*cb565728SJerry Jelinek * If the length of the actual resource descriptor is greater than the
173*cb565728SJerry Jelinek * ACPI spec-defined minimum length, it means that a ResourceSourceIndex
174*cb565728SJerry Jelinek * exists and is followed by a (required) null terminated string. The
175*cb565728SJerry Jelinek * string length (including the null terminator) is the resource length
176*cb565728SJerry Jelinek * minus the minimum length, minus one byte for the ResourceSourceIndex
177*cb565728SJerry Jelinek * itself.
178ae115bc7Smrj */
179ae115bc7Smrj if (ResourceLength > MinimumAmlResourceLength)
180ae115bc7Smrj {
181ae115bc7Smrj /* Compute the length of the optional string */
182ae115bc7Smrj
183ae115bc7Smrj StringLength = ResourceLength - MinimumAmlResourceLength - 1;
184ae115bc7Smrj }
185ae115bc7Smrj
186ae115bc7Smrj /*
187ae115bc7Smrj * Round the length up to a multiple of the native word in order to
188ae115bc7Smrj * guarantee that the entire resource descriptor is native word aligned
189ae115bc7Smrj */
190ae115bc7Smrj return ((UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (StringLength));
191ae115bc7Smrj }
192ae115bc7Smrj
193ae115bc7Smrj
194ae115bc7Smrj /*******************************************************************************
195ae115bc7Smrj *
196ae115bc7Smrj * FUNCTION: AcpiRsGetAmlLength
197ae115bc7Smrj *
198ae115bc7Smrj * PARAMETERS: Resource - Pointer to the resource linked list
199*cb565728SJerry Jelinek * ResourceListSize - Size of the resource linked list
200ae115bc7Smrj * SizeNeeded - Where the required size is returned
201ae115bc7Smrj *
202ae115bc7Smrj * RETURN: Status
203ae115bc7Smrj *
204ae115bc7Smrj * DESCRIPTION: Takes a linked list of internal resource descriptors and
205ae115bc7Smrj * calculates the size buffer needed to hold the corresponding
206ae115bc7Smrj * external resource byte stream.
207ae115bc7Smrj *
208ae115bc7Smrj ******************************************************************************/
209ae115bc7Smrj
210ae115bc7Smrj ACPI_STATUS
AcpiRsGetAmlLength(ACPI_RESOURCE * Resource,ACPI_SIZE ResourceListSize,ACPI_SIZE * SizeNeeded)211ae115bc7Smrj AcpiRsGetAmlLength (
212ae115bc7Smrj ACPI_RESOURCE *Resource,
213*cb565728SJerry Jelinek ACPI_SIZE ResourceListSize,
214ae115bc7Smrj ACPI_SIZE *SizeNeeded)
215ae115bc7Smrj {
216ae115bc7Smrj ACPI_SIZE AmlSizeNeeded = 0;
217*cb565728SJerry Jelinek ACPI_RESOURCE *ResourceEnd;
218ae115bc7Smrj ACPI_RS_LENGTH TotalSize;
219ae115bc7Smrj
220ae115bc7Smrj
221ae115bc7Smrj ACPI_FUNCTION_TRACE (RsGetAmlLength);
222ae115bc7Smrj
223ae115bc7Smrj
224ae115bc7Smrj /* Traverse entire list of internal resource descriptors */
225ae115bc7Smrj
226*cb565728SJerry Jelinek ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, ResourceListSize);
227*cb565728SJerry Jelinek while (Resource < ResourceEnd)
228ae115bc7Smrj {
229ae115bc7Smrj /* Validate the descriptor type */
230ae115bc7Smrj
231ae115bc7Smrj if (Resource->Type > ACPI_RESOURCE_TYPE_MAX)
232ae115bc7Smrj {
233ae115bc7Smrj return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
234ae115bc7Smrj }
235ae115bc7Smrj
236*cb565728SJerry Jelinek /* Sanity check the length. It must not be zero, or we loop forever */
237*cb565728SJerry Jelinek
238*cb565728SJerry Jelinek if (!Resource->Length)
239*cb565728SJerry Jelinek {
240*cb565728SJerry Jelinek return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
241*cb565728SJerry Jelinek }
242*cb565728SJerry Jelinek
243ae115bc7Smrj /* Get the base size of the (external stream) resource descriptor */
244ae115bc7Smrj
245ae115bc7Smrj TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type];
246ae115bc7Smrj
247ae115bc7Smrj /*
248ae115bc7Smrj * Augment the base size for descriptors with optional and/or
249ae115bc7Smrj * variable-length fields
250ae115bc7Smrj */
251ae115bc7Smrj switch (Resource->Type)
252ae115bc7Smrj {
253db2bae30SDana Myers case ACPI_RESOURCE_TYPE_IRQ:
254db2bae30SDana Myers
255db2bae30SDana Myers /* Length can be 3 or 2 */
256db2bae30SDana Myers
257db2bae30SDana Myers if (Resource->Data.Irq.DescriptorLength == 2)
258db2bae30SDana Myers {
259db2bae30SDana Myers TotalSize--;
260db2bae30SDana Myers }
261db2bae30SDana Myers break;
262db2bae30SDana Myers
263db2bae30SDana Myers
264db2bae30SDana Myers case ACPI_RESOURCE_TYPE_START_DEPENDENT:
265db2bae30SDana Myers
266db2bae30SDana Myers /* Length can be 1 or 0 */
267db2bae30SDana Myers
268db2bae30SDana Myers if (Resource->Data.Irq.DescriptorLength == 0)
269db2bae30SDana Myers {
270db2bae30SDana Myers TotalSize--;
271db2bae30SDana Myers }
272db2bae30SDana Myers break;
273db2bae30SDana Myers
274db2bae30SDana Myers
275ae115bc7Smrj case ACPI_RESOURCE_TYPE_VENDOR:
276ae115bc7Smrj /*
277ae115bc7Smrj * Vendor Defined Resource:
278ae115bc7Smrj * For a Vendor Specific resource, if the Length is between 1 and 7
279ae115bc7Smrj * it will be created as a Small Resource data type, otherwise it
280ae115bc7Smrj * is a Large Resource data type.
281ae115bc7Smrj */
282ae115bc7Smrj if (Resource->Data.Vendor.ByteLength > 7)
283ae115bc7Smrj {
284ae115bc7Smrj /* Base size of a Large resource descriptor */
285ae115bc7Smrj
286ae115bc7Smrj TotalSize = sizeof (AML_RESOURCE_LARGE_HEADER);
287ae115bc7Smrj }
288ae115bc7Smrj
289ae115bc7Smrj /* Add the size of the vendor-specific data */
290ae115bc7Smrj
291ae115bc7Smrj TotalSize = (ACPI_RS_LENGTH)
292ae115bc7Smrj (TotalSize + Resource->Data.Vendor.ByteLength);
293ae115bc7Smrj break;
294ae115bc7Smrj
295ae115bc7Smrj
296ae115bc7Smrj case ACPI_RESOURCE_TYPE_END_TAG:
297ae115bc7Smrj /*
298ae115bc7Smrj * End Tag:
299ae115bc7Smrj * We are done -- return the accumulated total size.
300ae115bc7Smrj */
301ae115bc7Smrj *SizeNeeded = AmlSizeNeeded + TotalSize;
302ae115bc7Smrj
303ae115bc7Smrj /* Normal exit */
304ae115bc7Smrj
305ae115bc7Smrj return_ACPI_STATUS (AE_OK);
306ae115bc7Smrj
307ae115bc7Smrj
308ae115bc7Smrj case ACPI_RESOURCE_TYPE_ADDRESS16:
309ae115bc7Smrj /*
310ae115bc7Smrj * 16-Bit Address Resource:
311ae115bc7Smrj * Add the size of the optional ResourceSource info
312ae115bc7Smrj */
313*cb565728SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize +
314*cb565728SJerry Jelinek AcpiRsStructOptionLength (
315ae115bc7Smrj &Resource->Data.Address16.ResourceSource));
316ae115bc7Smrj break;
317ae115bc7Smrj
318ae115bc7Smrj
319ae115bc7Smrj case ACPI_RESOURCE_TYPE_ADDRESS32:
320ae115bc7Smrj /*
321ae115bc7Smrj * 32-Bit Address Resource:
322ae115bc7Smrj * Add the size of the optional ResourceSource info
323ae115bc7Smrj */
324*cb565728SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize +
325*cb565728SJerry Jelinek AcpiRsStructOptionLength (
326ae115bc7Smrj &Resource->Data.Address32.ResourceSource));
327ae115bc7Smrj break;
328ae115bc7Smrj
329ae115bc7Smrj
330ae115bc7Smrj case ACPI_RESOURCE_TYPE_ADDRESS64:
331ae115bc7Smrj /*
332ae115bc7Smrj * 64-Bit Address Resource:
333ae115bc7Smrj * Add the size of the optional ResourceSource info
334ae115bc7Smrj */
335*cb565728SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize +
336*cb565728SJerry Jelinek AcpiRsStructOptionLength (
337ae115bc7Smrj &Resource->Data.Address64.ResourceSource));
338ae115bc7Smrj break;
339ae115bc7Smrj
340ae115bc7Smrj
341ae115bc7Smrj case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
342ae115bc7Smrj /*
343ae115bc7Smrj * Extended IRQ Resource:
344ae115bc7Smrj * Add the size of each additional optional interrupt beyond the
345ae115bc7Smrj * required 1 (4 bytes for each UINT32 interrupt number)
346ae115bc7Smrj */
347*cb565728SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize +
348ae115bc7Smrj ((Resource->Data.ExtendedIrq.InterruptCount - 1) * 4) +
349ae115bc7Smrj
350ae115bc7Smrj /* Add the size of the optional ResourceSource info */
351ae115bc7Smrj
352ae115bc7Smrj AcpiRsStructOptionLength (
353ae115bc7Smrj &Resource->Data.ExtendedIrq.ResourceSource));
354ae115bc7Smrj break;
355ae115bc7Smrj
356ae115bc7Smrj
357*cb565728SJerry Jelinek case ACPI_RESOURCE_TYPE_GPIO:
358*cb565728SJerry Jelinek
359*cb565728SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize +
360*cb565728SJerry Jelinek (Resource->Data.Gpio.PinTableLength * 2) +
361*cb565728SJerry Jelinek Resource->Data.Gpio.ResourceSource.StringLength +
362*cb565728SJerry Jelinek Resource->Data.Gpio.VendorLength);
363*cb565728SJerry Jelinek
364*cb565728SJerry Jelinek break;
365*cb565728SJerry Jelinek
366*cb565728SJerry Jelinek
367*cb565728SJerry Jelinek case ACPI_RESOURCE_TYPE_SERIAL_BUS:
368*cb565728SJerry Jelinek
369*cb565728SJerry Jelinek TotalSize = AcpiGbl_AmlResourceSerialBusSizes [
370*cb565728SJerry Jelinek Resource->Data.CommonSerialBus.Type];
371*cb565728SJerry Jelinek
372*cb565728SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize +
373*cb565728SJerry Jelinek Resource->Data.I2cSerialBus.ResourceSource.StringLength +
374*cb565728SJerry Jelinek Resource->Data.I2cSerialBus.VendorLength);
375*cb565728SJerry Jelinek
376*cb565728SJerry Jelinek break;
377*cb565728SJerry Jelinek
378ae115bc7Smrj default:
379*cb565728SJerry Jelinek
380ae115bc7Smrj break;
381ae115bc7Smrj }
382ae115bc7Smrj
383ae115bc7Smrj /* Update the total */
384ae115bc7Smrj
385ae115bc7Smrj AmlSizeNeeded += TotalSize;
386ae115bc7Smrj
387ae115bc7Smrj /* Point to the next object */
388ae115bc7Smrj
389ae115bc7Smrj Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length);
390ae115bc7Smrj }
391ae115bc7Smrj
392ae115bc7Smrj /* Did not find an EndTag resource descriptor */
393ae115bc7Smrj
394ae115bc7Smrj return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
395ae115bc7Smrj }
396ae115bc7Smrj
397ae115bc7Smrj
398ae115bc7Smrj /*******************************************************************************
399ae115bc7Smrj *
400ae115bc7Smrj * FUNCTION: AcpiRsGetListLength
401ae115bc7Smrj *
402ae115bc7Smrj * PARAMETERS: AmlBuffer - Pointer to the resource byte stream
403ae115bc7Smrj * AmlBufferLength - Size of AmlBuffer
404ae115bc7Smrj * SizeNeeded - Where the size needed is returned
405ae115bc7Smrj *
406ae115bc7Smrj * RETURN: Status
407ae115bc7Smrj *
408ae115bc7Smrj * DESCRIPTION: Takes an external resource byte stream and calculates the size
409ae115bc7Smrj * buffer needed to hold the corresponding internal resource
410ae115bc7Smrj * descriptor linked list.
411ae115bc7Smrj *
412ae115bc7Smrj ******************************************************************************/
413ae115bc7Smrj
414ae115bc7Smrj ACPI_STATUS
AcpiRsGetListLength(UINT8 * AmlBuffer,UINT32 AmlBufferLength,ACPI_SIZE * SizeNeeded)415ae115bc7Smrj AcpiRsGetListLength (
416ae115bc7Smrj UINT8 *AmlBuffer,
417ae115bc7Smrj UINT32 AmlBufferLength,
418ae115bc7Smrj ACPI_SIZE *SizeNeeded)
419ae115bc7Smrj {
420ae115bc7Smrj ACPI_STATUS Status;
421ae115bc7Smrj UINT8 *EndAml;
422ae115bc7Smrj UINT8 *Buffer;
423ae115bc7Smrj UINT32 BufferSize;
424ae115bc7Smrj UINT16 Temp16;
425ae115bc7Smrj UINT16 ResourceLength;
426ae115bc7Smrj UINT32 ExtraStructBytes;
427ae115bc7Smrj UINT8 ResourceIndex;
428ae115bc7Smrj UINT8 MinimumAmlResourceLength;
429*cb565728SJerry Jelinek AML_RESOURCE *AmlResource;
430ae115bc7Smrj
431ae115bc7Smrj
432ae115bc7Smrj ACPI_FUNCTION_TRACE (RsGetListLength);
433ae115bc7Smrj
434ae115bc7Smrj
435*cb565728SJerry Jelinek *SizeNeeded = ACPI_RS_SIZE_MIN; /* Minimum size is one EndTag */
436ae115bc7Smrj EndAml = AmlBuffer + AmlBufferLength;
437ae115bc7Smrj
438ae115bc7Smrj /* Walk the list of AML resource descriptors */
439ae115bc7Smrj
440ae115bc7Smrj while (AmlBuffer < EndAml)
441ae115bc7Smrj {
442ae115bc7Smrj /* Validate the Resource Type and Resource Length */
443ae115bc7Smrj
444*cb565728SJerry Jelinek Status = AcpiUtValidateResource (NULL, AmlBuffer, &ResourceIndex);
445ae115bc7Smrj if (ACPI_FAILURE (Status))
446ae115bc7Smrj {
447*cb565728SJerry Jelinek /*
448*cb565728SJerry Jelinek * Exit on failure. Cannot continue because the descriptor length
449*cb565728SJerry Jelinek * may be bogus also.
450*cb565728SJerry Jelinek */
451ae115bc7Smrj return_ACPI_STATUS (Status);
452ae115bc7Smrj }
453ae115bc7Smrj
454*cb565728SJerry Jelinek AmlResource = (void *) AmlBuffer;
455*cb565728SJerry Jelinek
456ae115bc7Smrj /* Get the resource length and base (minimum) AML size */
457ae115bc7Smrj
458ae115bc7Smrj ResourceLength = AcpiUtGetResourceLength (AmlBuffer);
459ae115bc7Smrj MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
460ae115bc7Smrj
461ae115bc7Smrj /*
462ae115bc7Smrj * Augment the size for descriptors with optional
463ae115bc7Smrj * and/or variable length fields
464ae115bc7Smrj */
465ae115bc7Smrj ExtraStructBytes = 0;
466ae115bc7Smrj Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer);
467ae115bc7Smrj
468ae115bc7Smrj switch (AcpiUtGetResourceType (AmlBuffer))
469ae115bc7Smrj {
470ae115bc7Smrj case ACPI_RESOURCE_NAME_IRQ:
471ae115bc7Smrj /*
472ae115bc7Smrj * IRQ Resource:
473ae115bc7Smrj * Get the number of bits set in the 16-bit IRQ mask
474ae115bc7Smrj */
475ae115bc7Smrj ACPI_MOVE_16_TO_16 (&Temp16, Buffer);
476ae115bc7Smrj ExtraStructBytes = AcpiRsCountSetBits (Temp16);
477ae115bc7Smrj break;
478ae115bc7Smrj
479ae115bc7Smrj
480ae115bc7Smrj case ACPI_RESOURCE_NAME_DMA:
481ae115bc7Smrj /*
482ae115bc7Smrj * DMA Resource:
483ae115bc7Smrj * Get the number of bits set in the 8-bit DMA mask
484ae115bc7Smrj */
485ae115bc7Smrj ExtraStructBytes = AcpiRsCountSetBits (*Buffer);
486ae115bc7Smrj break;
487ae115bc7Smrj
488ae115bc7Smrj
489ae115bc7Smrj case ACPI_RESOURCE_NAME_VENDOR_SMALL:
490ae115bc7Smrj case ACPI_RESOURCE_NAME_VENDOR_LARGE:
491ae115bc7Smrj /*
492ae115bc7Smrj * Vendor Resource:
493ae115bc7Smrj * Get the number of vendor data bytes
494ae115bc7Smrj */
495ae115bc7Smrj ExtraStructBytes = ResourceLength;
496*cb565728SJerry Jelinek
497*cb565728SJerry Jelinek /*
498*cb565728SJerry Jelinek * There is already one byte included in the minimum
499*cb565728SJerry Jelinek * descriptor size. If there are extra struct bytes,
500*cb565728SJerry Jelinek * subtract one from the count.
501*cb565728SJerry Jelinek */
502*cb565728SJerry Jelinek if (ExtraStructBytes)
503*cb565728SJerry Jelinek {
504*cb565728SJerry Jelinek ExtraStructBytes--;
505*cb565728SJerry Jelinek }
506ae115bc7Smrj break;
507ae115bc7Smrj
508ae115bc7Smrj
509ae115bc7Smrj case ACPI_RESOURCE_NAME_END_TAG:
510ae115bc7Smrj /*
511*cb565728SJerry Jelinek * End Tag: This is the normal exit
512ae115bc7Smrj */
513ae115bc7Smrj return_ACPI_STATUS (AE_OK);
514ae115bc7Smrj
515ae115bc7Smrj
516ae115bc7Smrj case ACPI_RESOURCE_NAME_ADDRESS32:
517ae115bc7Smrj case ACPI_RESOURCE_NAME_ADDRESS16:
518ae115bc7Smrj case ACPI_RESOURCE_NAME_ADDRESS64:
519ae115bc7Smrj /*
520ae115bc7Smrj * Address Resource:
521ae115bc7Smrj * Add the size of the optional ResourceSource
522ae115bc7Smrj */
523ae115bc7Smrj ExtraStructBytes = AcpiRsStreamOptionLength (
524ae115bc7Smrj ResourceLength, MinimumAmlResourceLength);
525ae115bc7Smrj break;
526ae115bc7Smrj
527ae115bc7Smrj
528ae115bc7Smrj case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
529ae115bc7Smrj /*
530ae115bc7Smrj * Extended IRQ Resource:
531ae115bc7Smrj * Using the InterruptTableLength, add 4 bytes for each additional
532ae115bc7Smrj * interrupt. Note: at least one interrupt is required and is
533ae115bc7Smrj * included in the minimum descriptor size (reason for the -1)
534ae115bc7Smrj */
535ae115bc7Smrj ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32);
536ae115bc7Smrj
537ae115bc7Smrj /* Add the size of the optional ResourceSource */
538ae115bc7Smrj
539ae115bc7Smrj ExtraStructBytes += AcpiRsStreamOptionLength (
540ae115bc7Smrj ResourceLength - ExtraStructBytes, MinimumAmlResourceLength);
541ae115bc7Smrj break;
542ae115bc7Smrj
543*cb565728SJerry Jelinek case ACPI_RESOURCE_NAME_GPIO:
544*cb565728SJerry Jelinek
545*cb565728SJerry Jelinek /* Vendor data is optional */
546*cb565728SJerry Jelinek
547*cb565728SJerry Jelinek if (AmlResource->Gpio.VendorLength)
548*cb565728SJerry Jelinek {
549*cb565728SJerry Jelinek ExtraStructBytes +=
550*cb565728SJerry Jelinek AmlResource->Gpio.VendorOffset -
551*cb565728SJerry Jelinek AmlResource->Gpio.PinTableOffset +
552*cb565728SJerry Jelinek AmlResource->Gpio.VendorLength;
553*cb565728SJerry Jelinek }
554*cb565728SJerry Jelinek else
555*cb565728SJerry Jelinek {
556*cb565728SJerry Jelinek ExtraStructBytes +=
557*cb565728SJerry Jelinek AmlResource->LargeHeader.ResourceLength +
558*cb565728SJerry Jelinek sizeof (AML_RESOURCE_LARGE_HEADER) -
559*cb565728SJerry Jelinek AmlResource->Gpio.PinTableOffset;
560*cb565728SJerry Jelinek }
561*cb565728SJerry Jelinek break;
562*cb565728SJerry Jelinek
563*cb565728SJerry Jelinek case ACPI_RESOURCE_NAME_SERIAL_BUS:
564*cb565728SJerry Jelinek
565*cb565728SJerry Jelinek MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[
566*cb565728SJerry Jelinek AmlResource->CommonSerialBus.Type];
567*cb565728SJerry Jelinek ExtraStructBytes +=
568*cb565728SJerry Jelinek AmlResource->CommonSerialBus.ResourceLength -
569*cb565728SJerry Jelinek MinimumAmlResourceLength;
570*cb565728SJerry Jelinek break;
571ae115bc7Smrj
572ae115bc7Smrj default:
573*cb565728SJerry Jelinek
574ae115bc7Smrj break;
575ae115bc7Smrj }
576ae115bc7Smrj
577ae115bc7Smrj /*
578ae115bc7Smrj * Update the required buffer size for the internal descriptor structs
579ae115bc7Smrj *
580ae115bc7Smrj * Important: Round the size up for the appropriate alignment. This
581ae115bc7Smrj * is a requirement on IA64.
582ae115bc7Smrj */
583*cb565728SJerry Jelinek if (AcpiUtGetResourceType (AmlBuffer) ==
584*cb565728SJerry Jelinek ACPI_RESOURCE_NAME_SERIAL_BUS)
585*cb565728SJerry Jelinek {
586*cb565728SJerry Jelinek BufferSize = AcpiGbl_ResourceStructSerialBusSizes[
587*cb565728SJerry Jelinek AmlResource->CommonSerialBus.Type] + ExtraStructBytes;
588*cb565728SJerry Jelinek }
589*cb565728SJerry Jelinek else
590*cb565728SJerry Jelinek {
591ae115bc7Smrj BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] +
592ae115bc7Smrj ExtraStructBytes;
593*cb565728SJerry Jelinek }
594ae115bc7Smrj
595*cb565728SJerry Jelinek BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize);
596ae115bc7Smrj *SizeNeeded += BufferSize;
597ae115bc7Smrj
598ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES,
599ae115bc7Smrj "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
600ae115bc7Smrj AcpiUtGetResourceType (AmlBuffer),
601ae115bc7Smrj AcpiUtGetDescriptorLength (AmlBuffer), BufferSize));
602ae115bc7Smrj
603ae115bc7Smrj /*
604ae115bc7Smrj * Point to the next resource within the AML stream using the length
605ae115bc7Smrj * contained in the resource descriptor header
606ae115bc7Smrj */
607ae115bc7Smrj AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer);
608ae115bc7Smrj }
609ae115bc7Smrj
610ae115bc7Smrj /* Did not find an EndTag resource descriptor */
611ae115bc7Smrj
612ae115bc7Smrj return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
613ae115bc7Smrj }
614ae115bc7Smrj
615ae115bc7Smrj
616ae115bc7Smrj /*******************************************************************************
617ae115bc7Smrj *
618ae115bc7Smrj * FUNCTION: AcpiRsGetPciRoutingTableLength
619ae115bc7Smrj *
620ae115bc7Smrj * PARAMETERS: PackageObject - Pointer to the package object
621ae115bc7Smrj * BufferSizeNeeded - UINT32 pointer of the size buffer
622ae115bc7Smrj * needed to properly return the
623ae115bc7Smrj * parsed data
624ae115bc7Smrj *
625ae115bc7Smrj * RETURN: Status
626ae115bc7Smrj *
627ae115bc7Smrj * DESCRIPTION: Given a package representing a PCI routing table, this
628ae115bc7Smrj * calculates the size of the corresponding linked list of
629ae115bc7Smrj * descriptions.
630ae115bc7Smrj *
631ae115bc7Smrj ******************************************************************************/
632ae115bc7Smrj
633ae115bc7Smrj ACPI_STATUS
AcpiRsGetPciRoutingTableLength(ACPI_OPERAND_OBJECT * PackageObject,ACPI_SIZE * BufferSizeNeeded)634ae115bc7Smrj AcpiRsGetPciRoutingTableLength (
635ae115bc7Smrj ACPI_OPERAND_OBJECT *PackageObject,
636ae115bc7Smrj ACPI_SIZE *BufferSizeNeeded)
637ae115bc7Smrj {
638ae115bc7Smrj UINT32 NumberOfElements;
639ae115bc7Smrj ACPI_SIZE TempSizeNeeded = 0;
640ae115bc7Smrj ACPI_OPERAND_OBJECT **TopObjectList;
641ae115bc7Smrj UINT32 Index;
642ae115bc7Smrj ACPI_OPERAND_OBJECT *PackageElement;
643ae115bc7Smrj ACPI_OPERAND_OBJECT **SubObjectList;
644ae115bc7Smrj BOOLEAN NameFound;
645ae115bc7Smrj UINT32 TableIndex;
646ae115bc7Smrj
647ae115bc7Smrj
648ae115bc7Smrj ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength);
649ae115bc7Smrj
650ae115bc7Smrj
651ae115bc7Smrj NumberOfElements = PackageObject->Package.Count;
652ae115bc7Smrj
653ae115bc7Smrj /*
654ae115bc7Smrj * Calculate the size of the return buffer.
655ae115bc7Smrj * The base size is the number of elements * the sizes of the
656ae115bc7Smrj * structures. Additional space for the strings is added below.
657ae115bc7Smrj * The minus one is to subtract the size of the UINT8 Source[1]
658ae115bc7Smrj * member because it is added below.
659ae115bc7Smrj *
660ae115bc7Smrj * But each PRT_ENTRY structure has a pointer to a string and
661ae115bc7Smrj * the size of that string must be found.
662ae115bc7Smrj */
663ae115bc7Smrj TopObjectList = PackageObject->Package.Elements;
664ae115bc7Smrj
665ae115bc7Smrj for (Index = 0; Index < NumberOfElements; Index++)
666ae115bc7Smrj {
667*cb565728SJerry Jelinek /* Dereference the subpackage */
668ae115bc7Smrj
669ae115bc7Smrj PackageElement = *TopObjectList;
670ae115bc7Smrj
671aa2aa9a6SDana Myers /* We must have a valid Package object */
672aa2aa9a6SDana Myers
673aa2aa9a6SDana Myers if (!PackageElement ||
674aa2aa9a6SDana Myers (PackageElement->Common.Type != ACPI_TYPE_PACKAGE))
675aa2aa9a6SDana Myers {
676aa2aa9a6SDana Myers return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
677aa2aa9a6SDana Myers }
678aa2aa9a6SDana Myers
679ae115bc7Smrj /*
680ae115bc7Smrj * The SubObjectList will now point to an array of the
681ae115bc7Smrj * four IRQ elements: Address, Pin, Source and SourceIndex
682ae115bc7Smrj */
683ae115bc7Smrj SubObjectList = PackageElement->Package.Elements;
684ae115bc7Smrj
685ae115bc7Smrj /* Scan the IrqTableElements for the Source Name String */
686ae115bc7Smrj
687ae115bc7Smrj NameFound = FALSE;
688ae115bc7Smrj
689*cb565728SJerry Jelinek for (TableIndex = 0;
690*cb565728SJerry Jelinek TableIndex < PackageElement->Package.Count && !NameFound;
691*cb565728SJerry Jelinek TableIndex++)
692ae115bc7Smrj {
693ae115bc7Smrj if (*SubObjectList && /* Null object allowed */
694ae115bc7Smrj
695ae115bc7Smrj ((ACPI_TYPE_STRING ==
696aa2aa9a6SDana Myers (*SubObjectList)->Common.Type) ||
697ae115bc7Smrj
698ae115bc7Smrj ((ACPI_TYPE_LOCAL_REFERENCE ==
699aa2aa9a6SDana Myers (*SubObjectList)->Common.Type) &&
700ae115bc7Smrj
701db2bae30SDana Myers ((*SubObjectList)->Reference.Class ==
702db2bae30SDana Myers ACPI_REFCLASS_NAME))))
703ae115bc7Smrj {
704ae115bc7Smrj NameFound = TRUE;
705ae115bc7Smrj }
706ae115bc7Smrj else
707ae115bc7Smrj {
708ae115bc7Smrj /* Look at the next element */
709ae115bc7Smrj
710ae115bc7Smrj SubObjectList++;
711ae115bc7Smrj }
712ae115bc7Smrj }
713ae115bc7Smrj
714ae115bc7Smrj TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);
715ae115bc7Smrj
716ae115bc7Smrj /* Was a String type found? */
717ae115bc7Smrj
718ae115bc7Smrj if (NameFound)
719ae115bc7Smrj {
720aa2aa9a6SDana Myers if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING)
721ae115bc7Smrj {
722ae115bc7Smrj /*
723ae115bc7Smrj * The length String.Length field does not include the
724ae115bc7Smrj * terminating NULL, add 1
725ae115bc7Smrj */
726ae115bc7Smrj TempSizeNeeded += ((ACPI_SIZE)
727ae115bc7Smrj (*SubObjectList)->String.Length + 1);
728ae115bc7Smrj }
729ae115bc7Smrj else
730ae115bc7Smrj {
731ae115bc7Smrj TempSizeNeeded += AcpiNsGetPathnameLength (
732ae115bc7Smrj (*SubObjectList)->Reference.Node);
733ae115bc7Smrj }
734ae115bc7Smrj }
735ae115bc7Smrj else
736ae115bc7Smrj {
737ae115bc7Smrj /*
738ae115bc7Smrj * If no name was found, then this is a NULL, which is
739ae115bc7Smrj * translated as a UINT32 zero.
740ae115bc7Smrj */
741ae115bc7Smrj TempSizeNeeded += sizeof (UINT32);
742ae115bc7Smrj }
743ae115bc7Smrj
744ae115bc7Smrj /* Round up the size since each element must be aligned */
745ae115bc7Smrj
746ae115bc7Smrj TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded);
747ae115bc7Smrj
748ae115bc7Smrj /* Point to the next ACPI_OPERAND_OBJECT */
749ae115bc7Smrj
750ae115bc7Smrj TopObjectList++;
751ae115bc7Smrj }
752ae115bc7Smrj
753ae115bc7Smrj /*
754ae115bc7Smrj * Add an extra element to the end of the list, essentially a
755ae115bc7Smrj * NULL terminator
756ae115bc7Smrj */
757ae115bc7Smrj *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE);
758ae115bc7Smrj return_ACPI_STATUS (AE_OK);
759ae115bc7Smrj }
760