1 /******************************************************************************
   2  *
   3  * Module Name: aslrestype2 - Miscellaneous Large resource descriptors
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 
  45 #include "aslcompiler.h"
  46 #include "aslcompiler.y.h"
  47 #include "amlcode.h"
  48 
  49 #define _COMPONENT          ACPI_COMPILER
  50         ACPI_MODULE_NAME    ("aslrestype2")
  51 
  52 /*
  53  * This module contains miscellaneous large resource descriptors:
  54  *
  55  * Register
  56  * Interrupt
  57  * VendorLong
  58  */
  59 
  60 /*******************************************************************************
  61  *
  62  * FUNCTION:    RsDoGeneralRegisterDescriptor
  63  *
  64  * PARAMETERS:  Op                  - Parent resource descriptor parse node
  65  *              CurrentByteOffset   - Offset into the resource template AML
  66  *                                    buffer (to track references to the desc)
  67  *
  68  * RETURN:      Completed resource node
  69  *
  70  * DESCRIPTION: Construct a long "Register" descriptor
  71  *
  72  ******************************************************************************/
  73 
  74 ASL_RESOURCE_NODE *
  75 RsDoGeneralRegisterDescriptor (
  76     ACPI_PARSE_OBJECT       *Op,
  77     UINT32                  CurrentByteOffset)
  78 {
  79     AML_RESOURCE            *Descriptor;
  80     ACPI_PARSE_OBJECT       *InitializerOp;
  81     ASL_RESOURCE_NODE       *Rnode;
  82     UINT32                  i;
  83 
  84 
  85     InitializerOp = Op->Asl.Child;
  86     Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_GENERIC_REGISTER));
  87 
  88     Descriptor = Rnode->Buffer;
  89     Descriptor->GenericReg.DescriptorType = ACPI_RESOURCE_NAME_GENERIC_REGISTER;
  90     Descriptor->GenericReg.ResourceLength = 12;
  91 
  92     /* Process all child initialization nodes */
  93 
  94     for (i = 0; InitializerOp; i++)
  95     {
  96         switch (i)
  97         {
  98         case 0: /* Address space */
  99 
 100             Descriptor->GenericReg.AddressSpaceId = (UINT8) InitializerOp->Asl.Value.Integer;
 101             RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESSSPACE,
 102                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AddressSpaceId));
 103            break;
 104 
 105         case 1: /* Register Bit Width */
 106 
 107             Descriptor->GenericReg.BitWidth = (UINT8) InitializerOp->Asl.Value.Integer;
 108             RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITWIDTH,
 109                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitWidth));
 110             break;
 111 
 112         case 2: /* Register Bit Offset */
 113 
 114             Descriptor->GenericReg.BitOffset = (UINT8) InitializerOp->Asl.Value.Integer;
 115             RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITOFFSET,
 116                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitOffset));
 117             break;
 118 
 119         case 3: /* Register Address */
 120 
 121             Descriptor->GenericReg.Address = InitializerOp->Asl.Value.Integer;
 122             RsCreateQwordField (InitializerOp, ACPI_RESTAG_ADDRESS,
 123                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.Address));
 124             break;
 125 
 126         case 4: /* Access Size (ACPI 3.0) */
 127 
 128             Descriptor->GenericReg.AccessSize = (UINT8) InitializerOp->Asl.Value.Integer;
 129             RsCreateByteField (InitializerOp, ACPI_RESTAG_ACCESSSIZE,
 130                 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AccessSize));
 131 
 132             if (Descriptor->GenericReg.AccessSize > AML_FIELD_ACCESS_QWORD)
 133             {
 134                 AslError (ASL_ERROR, ASL_MSG_INVALID_ACCESS_SIZE,
 135                     InitializerOp, NULL);
 136             }
 137             break;
 138 
 139         case 5: /* ResourceTag (ACPI 3.0b) */
 140 
 141             UtAttachNamepathToOwner (Op, InitializerOp);
 142             break;
 143 
 144         default:
 145 
 146             AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
 147             break;
 148         }
 149 
 150         InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
 151     }
 152     return (Rnode);
 153 }
 154 
 155 
 156 /*******************************************************************************
 157  *
 158  * FUNCTION:    RsDoInterruptDescriptor
 159  *
 160  * PARAMETERS:  Op                  - Parent resource descriptor parse node
 161  *              CurrentByteOffset   - Offset into the resource template AML
 162  *                                    buffer (to track references to the desc)
 163  *
 164  * RETURN:      Completed resource node
 165  *
 166  * DESCRIPTION: Construct a long "Interrupt" descriptor
 167  *
 168  ******************************************************************************/
 169 
 170 ASL_RESOURCE_NODE *
 171 RsDoInterruptDescriptor (
 172     ACPI_PARSE_OBJECT       *Op,
 173     UINT32                  CurrentByteOffset)
 174 {
 175     AML_RESOURCE            *Descriptor;
 176     AML_RESOURCE            *Rover = NULL;
 177     ACPI_PARSE_OBJECT       *InitializerOp;
 178     ASL_RESOURCE_NODE       *Rnode;
 179     UINT16                  StringLength = 0;
 180     UINT32                  OptionIndex = 0;
 181     UINT32                  i;
 182     BOOLEAN                 HasResSourceIndex = FALSE;
 183     UINT8                   ResSourceIndex = 0;
 184     UINT8                   *ResSourceString = NULL;
 185 
 186 
 187     InitializerOp = Op->Asl.Child;
 188     StringLength = RsGetStringDataLength (InitializerOp);
 189 
 190     /* Count the interrupt numbers */
 191 
 192     for (i = 0; InitializerOp; i++)
 193     {
 194         InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
 195 
 196         if (i <= 6)
 197         {
 198             if (i == 3 &&
 199                 InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
 200             {
 201                 /*
 202                  * ResourceSourceIndex was specified, always make room for
 203                  * it, even if the ResourceSource was omitted.
 204                  */
 205                 OptionIndex++;
 206             }
 207 
 208             continue;
 209         }
 210 
 211         OptionIndex += 4;
 212     }
 213 
 214     InitializerOp = Op->Asl.Child;
 215     Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_EXTENDED_IRQ) +
 216                 1 + OptionIndex + StringLength);
 217 
 218     Descriptor = Rnode->Buffer;
 219     Descriptor->ExtendedIrq.DescriptorType  = ACPI_RESOURCE_NAME_EXTENDED_IRQ;
 220 
 221     /*
 222      * Initial descriptor length -- may be enlarged if there are
 223      * optional fields present
 224      */
 225     Descriptor->ExtendedIrq.ResourceLength  = 2;  /* Flags and table length byte */
 226     Descriptor->ExtendedIrq.InterruptCount  = 0;
 227 
 228     Rover = ACPI_CAST_PTR (AML_RESOURCE,
 229                 (&(Descriptor->ExtendedIrq.Interrupts[0])));
 230 
 231     /* Process all child initialization nodes */
 232 
 233     for (i = 0; InitializerOp; i++)
 234     {
 235         switch (i)
 236         {
 237         case 0: /* Resource Usage (Default: consumer (1) */
 238 
 239             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 0, 1);
 240             break;
 241 
 242         case 1: /* Interrupt Type (or Mode - edge/level) */
 243 
 244             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 1, 0);
 245             RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE,
 246                 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 1);
 247             break;
 248 
 249         case 2: /* Interrupt Level (or Polarity - Active high/low) */
 250 
 251             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 2, 0);
 252             RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL,
 253                 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 2);
 254             break;
 255 
 256         case 3: /* Share Type - Default: exclusive (0) */
 257 
 258             RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 3, 0);
 259             RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE,
 260                 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 3);
 261             break;
 262 
 263         case 4: /* ResSourceIndex [Optional Field - BYTE] */
 264 
 265             if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
 266             {
 267                 HasResSourceIndex = TRUE;
 268                 ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer;
 269             }
 270             break;
 271 
 272         case 5: /* ResSource [Optional Field - STRING] */
 273 
 274             if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
 275                 (InitializerOp->Asl.Value.String))
 276             {
 277                 if (StringLength)
 278                 {
 279                     ResSourceString = (UINT8 *) InitializerOp->Asl.Value.String;
 280                 }
 281 
 282                 /* ResourceSourceIndex must also be valid */
 283 
 284                 if (!HasResSourceIndex)
 285                 {
 286                     AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
 287                         InitializerOp, NULL);
 288                 }
 289             }
 290 
 291 #if 0
 292             /*
 293              * Not a valid ResourceSource, ResourceSourceIndex must also
 294              * be invalid
 295              */
 296             else if (HasResSourceIndex)
 297             {
 298                 AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
 299                     InitializerOp, NULL);
 300             }
 301 #endif
 302             break;
 303 
 304         case 6: /* ResourceTag */
 305 
 306             UtAttachNamepathToOwner (Op, InitializerOp);
 307             break;
 308 
 309         default:
 310             /*
 311              * Interrupt Numbers come through here, repeatedly
 312              */
 313 
 314             /* Maximum 255 interrupts allowed for this descriptor */
 315 
 316             if (Descriptor->ExtendedIrq.InterruptCount == 255)
 317             {
 318                 AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST,
 319                     InitializerOp, NULL);
 320                 return (Rnode);
 321             }
 322 
 323             /* Each interrupt number must be a 32-bit value */
 324 
 325             if (InitializerOp->Asl.Value.Integer > ACPI_UINT32_MAX)
 326             {
 327                 AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_NUMBER,
 328                     InitializerOp, NULL);
 329             }
 330 
 331             /* Save the integer and move pointer to the next one */
 332 
 333             Rover->DwordItem = (UINT32) InitializerOp->Asl.Value.Integer;
 334             Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->DwordItem), 4);
 335             Descriptor->ExtendedIrq.InterruptCount++;
 336             Descriptor->ExtendedIrq.ResourceLength += 4;
 337 
 338             /* Case 7: First interrupt number in list */
 339 
 340             if (i == 7)
 341             {
 342                 if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
 343                 {
 344                     /* Must be at least one interrupt */
 345 
 346                     AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST_MIN,
 347                         InitializerOp, NULL);
 348                 }
 349 
 350                 /* Check now for duplicates in list */
 351 
 352                 RsCheckListForDuplicates (InitializerOp);
 353 
 354                 /* Create a named field at the start of the list */
 355 
 356                 RsCreateDwordField (InitializerOp, ACPI_RESTAG_INTERRUPT,
 357                     CurrentByteOffset +
 358                     ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0]));
 359             }
 360         }
 361 
 362         InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
 363     }
 364 
 365 
 366     /* Add optional ResSourceIndex if present */
 367 
 368     if (HasResSourceIndex)
 369     {
 370         Rover->ByteItem = ResSourceIndex;
 371         Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->ByteItem), 1);
 372         Descriptor->ExtendedIrq.ResourceLength += 1;
 373     }
 374 
 375     /* Add optional ResSource string if present */
 376 
 377     if (StringLength && ResSourceString)
 378     {
 379 
 380         strcpy ((char *) Rover, (char *) ResSourceString);
 381         Rover = ACPI_ADD_PTR (
 382                     AML_RESOURCE, &(Rover->ByteItem), StringLength);
 383 
 384         Descriptor->ExtendedIrq.ResourceLength = (UINT16)
 385             (Descriptor->ExtendedIrq.ResourceLength + StringLength);
 386     }
 387 
 388     Rnode->BufferLength = (ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0]) -
 389                            ASL_RESDESC_OFFSET (ExtendedIrq.DescriptorType))
 390                            + OptionIndex + StringLength;
 391     return (Rnode);
 392 }
 393 
 394 
 395 /*******************************************************************************
 396  *
 397  * FUNCTION:    RsDoVendorLargeDescriptor
 398  *
 399  * PARAMETERS:  Op                  - Parent resource descriptor parse node
 400  *              CurrentByteOffset   - Offset into the resource template AML
 401  *                                    buffer (to track references to the desc)
 402  *
 403  * RETURN:      Completed resource node
 404  *
 405  * DESCRIPTION: Construct a long "VendorLong" descriptor
 406  *
 407  ******************************************************************************/
 408 
 409 ASL_RESOURCE_NODE *
 410 RsDoVendorLargeDescriptor (
 411     ACPI_PARSE_OBJECT       *Op,
 412     UINT32                  CurrentByteOffset)
 413 {
 414     AML_RESOURCE            *Descriptor;
 415     ACPI_PARSE_OBJECT       *InitializerOp;
 416     ASL_RESOURCE_NODE       *Rnode;
 417     UINT8                   *VendorData;
 418     UINT32                  i;
 419 
 420 
 421     /* Count the number of data bytes */
 422 
 423     InitializerOp = Op->Asl.Child;
 424     InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
 425 
 426     for (i = 0; InitializerOp; i++)
 427     {
 428         if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
 429         {
 430             break;
 431         }
 432         InitializerOp = InitializerOp->Asl.Next;
 433     }
 434 
 435     InitializerOp = Op->Asl.Child;
 436     InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
 437     Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_VENDOR_LARGE) + i);
 438 
 439     Descriptor = Rnode->Buffer;
 440     Descriptor->VendorLarge.DescriptorType  = ACPI_RESOURCE_NAME_VENDOR_LARGE;
 441     Descriptor->VendorLarge.ResourceLength = (UINT16) i;
 442 
 443     /* Point to end-of-descriptor for vendor data */
 444 
 445     VendorData = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_LARGE_HEADER);
 446 
 447     /* Process all child initialization nodes */
 448 
 449     for (i = 0; InitializerOp; i++)
 450     {
 451         if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
 452         {
 453             break;
 454         }
 455 
 456         VendorData[i] = (UINT8) InitializerOp->Asl.Value.Integer;
 457         InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
 458     }
 459 
 460     return (Rnode);
 461 }