1ae115bc7Smrj /******************************************************************************* 2ae115bc7Smrj * 3ae115bc7Smrj * Module Name: rscalc - Calculate stream and list lengths 4ae115bc7Smrj * 5ae115bc7Smrj ******************************************************************************/ 6ae115bc7Smrj 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry 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 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 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 156ae115bc7Smrj AcpiRsStreamOptionLength ( 157ae115bc7Smrj UINT32 ResourceLength, 158ae115bc7Smrj UINT32 MinimumAmlResourceLength) 159ae115bc7Smrj { 160ae115bc7Smrj UINT32 StringLength = 0; 161ae115bc7Smrj 162ae115bc7Smrj 163ae115bc7Smrj ACPI_FUNCTION_ENTRY (); 164ae115bc7Smrj 165ae115bc7Smrj 166ae115bc7Smrj /* 167*385cc6b4SJerry Jelinek * The ResourceSourceIndex and ResourceSource are optional elements of 168*385cc6b4SJerry Jelinek * some Large-type resource descriptors. 169ae115bc7Smrj */ 170ae115bc7Smrj 171ae115bc7Smrj /* 172*385cc6b4SJerry Jelinek * If the length of the actual resource descriptor is greater than the 173*385cc6b4SJerry Jelinek * ACPI spec-defined minimum length, it means that a ResourceSourceIndex 174*385cc6b4SJerry Jelinek * exists and is followed by a (required) null terminated string. The 175*385cc6b4SJerry Jelinek * string length (including the null terminator) is the resource length 176*385cc6b4SJerry Jelinek * minus the minimum length, minus one byte for the ResourceSourceIndex 177*385cc6b4SJerry 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*385cc6b4SJerry 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 211ae115bc7Smrj AcpiRsGetAmlLength ( 212ae115bc7Smrj ACPI_RESOURCE *Resource, 213*385cc6b4SJerry Jelinek ACPI_SIZE ResourceListSize, 214ae115bc7Smrj ACPI_SIZE *SizeNeeded) 215ae115bc7Smrj { 216ae115bc7Smrj ACPI_SIZE AmlSizeNeeded = 0; 217*385cc6b4SJerry 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*385cc6b4SJerry Jelinek ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, ResourceListSize); 227*385cc6b4SJerry 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*385cc6b4SJerry Jelinek /* Sanity check the length. It must not be zero, or we loop forever */ 237*385cc6b4SJerry Jelinek 238*385cc6b4SJerry Jelinek if (!Resource->Length) 239*385cc6b4SJerry Jelinek { 240*385cc6b4SJerry Jelinek return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); 241*385cc6b4SJerry Jelinek } 242*385cc6b4SJerry 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*385cc6b4SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize + 314*385cc6b4SJerry 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*385cc6b4SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize + 325*385cc6b4SJerry 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*385cc6b4SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize + 336*385cc6b4SJerry 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*385cc6b4SJerry 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*385cc6b4SJerry Jelinek case ACPI_RESOURCE_TYPE_GPIO: 358*385cc6b4SJerry Jelinek 359*385cc6b4SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize + 360*385cc6b4SJerry Jelinek (Resource->Data.Gpio.PinTableLength * 2) + 361*385cc6b4SJerry Jelinek Resource->Data.Gpio.ResourceSource.StringLength + 362*385cc6b4SJerry Jelinek Resource->Data.Gpio.VendorLength); 363*385cc6b4SJerry Jelinek 364*385cc6b4SJerry Jelinek break; 365*385cc6b4SJerry Jelinek 366*385cc6b4SJerry Jelinek 367*385cc6b4SJerry Jelinek case ACPI_RESOURCE_TYPE_SERIAL_BUS: 368*385cc6b4SJerry Jelinek 369*385cc6b4SJerry Jelinek TotalSize = AcpiGbl_AmlResourceSerialBusSizes [ 370*385cc6b4SJerry Jelinek Resource->Data.CommonSerialBus.Type]; 371*385cc6b4SJerry Jelinek 372*385cc6b4SJerry Jelinek TotalSize = (ACPI_RS_LENGTH) (TotalSize + 373*385cc6b4SJerry Jelinek Resource->Data.I2cSerialBus.ResourceSource.StringLength + 374*385cc6b4SJerry Jelinek Resource->Data.I2cSerialBus.VendorLength); 375*385cc6b4SJerry Jelinek 376*385cc6b4SJerry Jelinek break; 377*385cc6b4SJerry Jelinek 378ae115bc7Smrj default: 379*385cc6b4SJerry 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 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*385cc6b4SJerry Jelinek AML_RESOURCE *AmlResource; 430ae115bc7Smrj 431ae115bc7Smrj 432ae115bc7Smrj ACPI_FUNCTION_TRACE (RsGetListLength); 433ae115bc7Smrj 434ae115bc7Smrj 435*385cc6b4SJerry 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*385cc6b4SJerry Jelinek Status = AcpiUtValidateResource (NULL, AmlBuffer, &ResourceIndex); 445ae115bc7Smrj if (ACPI_FAILURE (Status)) 446ae115bc7Smrj { 447*385cc6b4SJerry Jelinek /* 448*385cc6b4SJerry Jelinek * Exit on failure. Cannot continue because the descriptor length 449*385cc6b4SJerry Jelinek * may be bogus also. 450*385cc6b4SJerry Jelinek */ 451ae115bc7Smrj return_ACPI_STATUS (Status); 452ae115bc7Smrj } 453ae115bc7Smrj 454*385cc6b4SJerry Jelinek AmlResource = (void *) AmlBuffer; 455*385cc6b4SJerry 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*385cc6b4SJerry Jelinek 497*385cc6b4SJerry Jelinek /* 498*385cc6b4SJerry Jelinek * There is already one byte included in the minimum 499*385cc6b4SJerry Jelinek * descriptor size. If there are extra struct bytes, 500*385cc6b4SJerry Jelinek * subtract one from the count. 501*385cc6b4SJerry Jelinek */ 502*385cc6b4SJerry Jelinek if (ExtraStructBytes) 503*385cc6b4SJerry Jelinek { 504*385cc6b4SJerry Jelinek ExtraStructBytes--; 505*385cc6b4SJerry Jelinek } 506ae115bc7Smrj break; 507ae115bc7Smrj 508ae115bc7Smrj 509ae115bc7Smrj case ACPI_RESOURCE_NAME_END_TAG: 510ae115bc7Smrj /* 511*385cc6b4SJerry 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*385cc6b4SJerry Jelinek case ACPI_RESOURCE_NAME_GPIO: 544*385cc6b4SJerry Jelinek 545*385cc6b4SJerry Jelinek /* Vendor data is optional */ 546*385cc6b4SJerry Jelinek 547*385cc6b4SJerry Jelinek if (AmlResource->Gpio.VendorLength) 548*385cc6b4SJerry Jelinek { 549*385cc6b4SJerry Jelinek ExtraStructBytes += 550*385cc6b4SJerry Jelinek AmlResource->Gpio.VendorOffset - 551*385cc6b4SJerry Jelinek AmlResource->Gpio.PinTableOffset + 552*385cc6b4SJerry Jelinek AmlResource->Gpio.VendorLength; 553*385cc6b4SJerry Jelinek } 554*385cc6b4SJerry Jelinek else 555*385cc6b4SJerry Jelinek { 556*385cc6b4SJerry Jelinek ExtraStructBytes += 557*385cc6b4SJerry Jelinek AmlResource->LargeHeader.ResourceLength + 558*385cc6b4SJerry Jelinek sizeof (AML_RESOURCE_LARGE_HEADER) - 559*385cc6b4SJerry Jelinek AmlResource->Gpio.PinTableOffset; 560*385cc6b4SJerry Jelinek } 561*385cc6b4SJerry Jelinek break; 562*385cc6b4SJerry Jelinek 563*385cc6b4SJerry Jelinek case ACPI_RESOURCE_NAME_SERIAL_BUS: 564*385cc6b4SJerry Jelinek 565*385cc6b4SJerry Jelinek MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[ 566*385cc6b4SJerry Jelinek AmlResource->CommonSerialBus.Type]; 567*385cc6b4SJerry Jelinek ExtraStructBytes += 568*385cc6b4SJerry Jelinek AmlResource->CommonSerialBus.ResourceLength - 569*385cc6b4SJerry Jelinek MinimumAmlResourceLength; 570*385cc6b4SJerry Jelinek break; 571ae115bc7Smrj 572ae115bc7Smrj default: 573*385cc6b4SJerry 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*385cc6b4SJerry Jelinek if (AcpiUtGetResourceType (AmlBuffer) == 584*385cc6b4SJerry Jelinek ACPI_RESOURCE_NAME_SERIAL_BUS) 585*385cc6b4SJerry Jelinek { 586*385cc6b4SJerry Jelinek BufferSize = AcpiGbl_ResourceStructSerialBusSizes[ 587*385cc6b4SJerry Jelinek AmlResource->CommonSerialBus.Type] + ExtraStructBytes; 588*385cc6b4SJerry Jelinek } 589*385cc6b4SJerry Jelinek else 590*385cc6b4SJerry Jelinek { 591ae115bc7Smrj BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] + 592ae115bc7Smrj ExtraStructBytes; 593*385cc6b4SJerry Jelinek } 594ae115bc7Smrj 595*385cc6b4SJerry 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 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*385cc6b4SJerry 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*385cc6b4SJerry Jelinek for (TableIndex = 0; 690*385cc6b4SJerry Jelinek TableIndex < PackageElement->Package.Count && !NameFound; 691*385cc6b4SJerry 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