1 /****************************************************************************** 2 * 3 * Module Name: aslrestype2 - Miscellaneous Large resource descriptors 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 #include "aslcompiler.h" 45 #include "aslcompiler.y.h" 46 #include "amlcode.h" 47 48 #define _COMPONENT ACPI_COMPILER 49 ACPI_MODULE_NAME ("aslrestype2") 50 51 /* 52 * This module contains miscellaneous large resource descriptors: 53 * 54 * Register 55 * Interrupt 56 * VendorLong 57 */ 58 59 /******************************************************************************* 60 * 61 * FUNCTION: RsDoGeneralRegisterDescriptor 62 * 63 * PARAMETERS: Info - Parse Op and resource template offset 64 * 65 * RETURN: Completed resource node 66 * 67 * DESCRIPTION: Construct a long "Register" descriptor 68 * 69 ******************************************************************************/ 70 71 ASL_RESOURCE_NODE * 72 RsDoGeneralRegisterDescriptor ( 73 ASL_RESOURCE_INFO *Info) 74 { 75 AML_RESOURCE *Descriptor; 76 ACPI_PARSE_OBJECT *InitializerOp; 77 ASL_RESOURCE_NODE *Rnode; 78 UINT32 CurrentByteOffset; 79 UINT32 i; 80 81 82 InitializerOp = Info->DescriptorTypeOp->Asl.Child; 83 CurrentByteOffset = Info->CurrentByteOffset; 84 Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_GENERIC_REGISTER)); 85 86 Descriptor = Rnode->Buffer; 87 Descriptor->GenericReg.DescriptorType = ACPI_RESOURCE_NAME_GENERIC_REGISTER; 88 Descriptor->GenericReg.ResourceLength = 12; 89 90 /* Process all child initialization nodes */ 91 92 for (i = 0; InitializerOp; i++) 93 { 94 switch (i) 95 { 96 case 0: /* Address space */ 97 98 Descriptor->GenericReg.AddressSpaceId = (UINT8) InitializerOp->Asl.Value.Integer; 99 RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESSSPACE, 100 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AddressSpaceId)); 101 break; 102 103 case 1: /* Register Bit Width */ 104 105 Descriptor->GenericReg.BitWidth = (UINT8) InitializerOp->Asl.Value.Integer; 106 RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITWIDTH, 107 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitWidth)); 108 break; 109 110 case 2: /* Register Bit Offset */ 111 112 Descriptor->GenericReg.BitOffset = (UINT8) InitializerOp->Asl.Value.Integer; 113 RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITOFFSET, 114 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitOffset)); 115 break; 116 117 case 3: /* Register Address */ 118 119 Descriptor->GenericReg.Address = InitializerOp->Asl.Value.Integer; 120 RsCreateQwordField (InitializerOp, ACPI_RESTAG_ADDRESS, 121 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.Address)); 122 break; 123 124 case 4: /* Access Size (ACPI 3.0) */ 125 126 Descriptor->GenericReg.AccessSize = (UINT8) InitializerOp->Asl.Value.Integer; 127 RsCreateByteField (InitializerOp, ACPI_RESTAG_ACCESSSIZE, 128 CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AccessSize)); 129 130 if (Descriptor->GenericReg.AddressSpaceId == ACPI_ADR_SPACE_PLATFORM_COMM) 131 { 132 break; 133 } 134 135 if (Descriptor->GenericReg.AccessSize > AML_FIELD_ACCESS_QWORD) 136 { 137 AslError (ASL_ERROR, ASL_MSG_INVALID_ACCESS_SIZE, 138 InitializerOp, NULL); 139 } 140 break; 141 142 case 5: /* ResourceTag (ACPI 3.0b) */ 143 144 UtAttachNamepathToOwner (Info->DescriptorTypeOp, InitializerOp); 145 break; 146 147 default: 148 149 AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); 150 break; 151 } 152 153 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); 154 } 155 156 return (Rnode); 157 } 158 159 160 /******************************************************************************* 161 * 162 * FUNCTION: RsDoInterruptDescriptor 163 * 164 * PARAMETERS: Info - Parse Op and resource template offset 165 * 166 * RETURN: Completed resource node 167 * 168 * DESCRIPTION: Construct a long "Interrupt" descriptor 169 * 170 ******************************************************************************/ 171 172 ASL_RESOURCE_NODE * 173 RsDoInterruptDescriptor ( 174 ASL_RESOURCE_INFO *Info) 175 { 176 AML_RESOURCE *Descriptor; 177 AML_RESOURCE *Rover = NULL; 178 ACPI_PARSE_OBJECT *InitializerOp; 179 ASL_RESOURCE_NODE *Rnode; 180 UINT16 StringLength = 0; 181 UINT32 OptionIndex = 0; 182 UINT32 CurrentByteOffset; 183 UINT32 i; 184 BOOLEAN HasResSourceIndex = FALSE; 185 UINT8 ResSourceIndex = 0; 186 UINT8 *ResSourceString = NULL; 187 188 189 InitializerOp = Info->DescriptorTypeOp->Asl.Child; 190 CurrentByteOffset = Info->CurrentByteOffset; 191 StringLength = RsGetStringDataLength (InitializerOp); 192 193 /* Count the interrupt numbers */ 194 195 for (i = 0; InitializerOp; i++) 196 { 197 InitializerOp = ASL_GET_PEER_NODE (InitializerOp); 198 199 if (i <= 6) 200 { 201 if (i == 3 && 202 InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 203 { 204 /* 205 * ResourceSourceIndex was specified, always make room for 206 * it, even if the ResourceSource was omitted. 207 */ 208 OptionIndex++; 209 } 210 211 continue; 212 } 213 214 OptionIndex += 4; 215 } 216 217 InitializerOp = Info->DescriptorTypeOp->Asl.Child; 218 Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_EXTENDED_IRQ) + 219 1 + OptionIndex + StringLength); 220 221 Descriptor = Rnode->Buffer; 222 Descriptor->ExtendedIrq.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_IRQ; 223 224 /* 225 * Initial descriptor length -- may be enlarged if there are 226 * optional fields present 227 */ 228 Descriptor->ExtendedIrq.ResourceLength = 2; /* Flags and table length byte */ 229 Descriptor->ExtendedIrq.InterruptCount = 0; 230 231 Rover = ACPI_CAST_PTR (AML_RESOURCE, 232 (&(Descriptor->ExtendedIrq.Interrupts[0]))); 233 234 /* Process all child initialization nodes */ 235 236 for (i = 0; InitializerOp; i++) 237 { 238 switch (i) 239 { 240 case 0: /* Resource Usage (Default: consumer (1) */ 241 242 RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 0, 1); 243 break; 244 245 case 1: /* Interrupt Type (or Mode - edge/level) */ 246 247 RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 1, 0); 248 RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE, 249 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 1); 250 break; 251 252 case 2: /* Interrupt Level (or Polarity - Active high/low) */ 253 254 RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 2, 0); 255 RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL, 256 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 2); 257 break; 258 259 case 3: /* Share Type - Default: exclusive (0) */ 260 261 RsSetFlagBits (&Descriptor->ExtendedIrq.Flags, InitializerOp, 3, 0); 262 RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE, 263 CurrentByteOffset + ASL_RESDESC_OFFSET (ExtendedIrq.Flags), 3); 264 break; 265 266 case 4: /* ResSourceIndex [Optional Field - BYTE] */ 267 268 if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 269 { 270 HasResSourceIndex = TRUE; 271 ResSourceIndex = (UINT8) InitializerOp->Asl.Value.Integer; 272 } 273 break; 274 275 case 5: /* ResSource [Optional Field - STRING] */ 276 277 if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && 278 (InitializerOp->Asl.Value.String)) 279 { 280 if (StringLength) 281 { 282 ResSourceString = (UINT8 *) InitializerOp->Asl.Value.String; 283 } 284 285 /* ResourceSourceIndex must also be valid */ 286 287 if (!HasResSourceIndex) 288 { 289 AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, 290 InitializerOp, NULL); 291 } 292 } 293 294 #if 0 295 /* 296 * Not a valid ResourceSource, ResourceSourceIndex must also 297 * be invalid 298 */ 299 else if (HasResSourceIndex) 300 { 301 AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, 302 InitializerOp, NULL); 303 } 304 #endif 305 break; 306 307 case 6: /* ResourceTag */ 308 309 UtAttachNamepathToOwner (Info->DescriptorTypeOp, InitializerOp); 310 break; 311 312 default: 313 /* 314 * Interrupt Numbers come through here, repeatedly 315 */ 316 317 /* Maximum 255 interrupts allowed for this descriptor */ 318 319 if (Descriptor->ExtendedIrq.InterruptCount == 255) 320 { 321 AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST, 322 InitializerOp, NULL); 323 return (Rnode); 324 } 325 326 /* Each interrupt number must be a 32-bit value */ 327 328 if (InitializerOp->Asl.Value.Integer > ACPI_UINT32_MAX) 329 { 330 AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_NUMBER, 331 InitializerOp, NULL); 332 } 333 334 /* Save the integer and move pointer to the next one */ 335 336 Rover->DwordItem = (UINT32) InitializerOp->Asl.Value.Integer; 337 Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->DwordItem), 4); 338 Descriptor->ExtendedIrq.InterruptCount++; 339 Descriptor->ExtendedIrq.ResourceLength += 4; 340 341 /* Case 7: First interrupt number in list */ 342 343 if (i == 7) 344 { 345 if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 346 { 347 /* Must be at least one interrupt */ 348 349 AslError (ASL_ERROR, ASL_MSG_EX_INTERRUPT_LIST_MIN, 350 InitializerOp, NULL); 351 } 352 353 /* Check now for duplicates in list */ 354 355 RsCheckListForDuplicates (InitializerOp); 356 357 /* Create a named field at the start of the list */ 358 359 RsCreateDwordField (InitializerOp, ACPI_RESTAG_INTERRUPT, 360 CurrentByteOffset + 361 ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0])); 362 } 363 } 364 365 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); 366 } 367 368 369 /* Add optional ResSourceIndex if present */ 370 371 if (HasResSourceIndex) 372 { 373 Rover->ByteItem = ResSourceIndex; 374 Rover = ACPI_ADD_PTR (AML_RESOURCE, &(Rover->ByteItem), 1); 375 Descriptor->ExtendedIrq.ResourceLength += 1; 376 } 377 378 /* Add optional ResSource string if present */ 379 380 if (StringLength && ResSourceString) 381 { 382 383 strcpy ((char *) Rover, (char *) ResSourceString); 384 Rover = ACPI_ADD_PTR ( 385 AML_RESOURCE, &(Rover->ByteItem), StringLength); 386 387 Descriptor->ExtendedIrq.ResourceLength = (UINT16) 388 (Descriptor->ExtendedIrq.ResourceLength + StringLength); 389 } 390 391 Rnode->BufferLength = 392 (ASL_RESDESC_OFFSET (ExtendedIrq.Interrupts[0]) - 393 ASL_RESDESC_OFFSET (ExtendedIrq.DescriptorType)) 394 + OptionIndex + StringLength; 395 return (Rnode); 396 } 397 398 399 /******************************************************************************* 400 * 401 * FUNCTION: RsDoVendorLargeDescriptor 402 * 403 * PARAMETERS: Info - Parse Op and resource template offset 404 * 405 * RETURN: Completed resource node 406 * 407 * DESCRIPTION: Construct a long "VendorLong" descriptor 408 * 409 ******************************************************************************/ 410 411 ASL_RESOURCE_NODE * 412 RsDoVendorLargeDescriptor ( 413 ASL_RESOURCE_INFO *Info) 414 { 415 AML_RESOURCE *Descriptor; 416 ACPI_PARSE_OBJECT *InitializerOp; 417 ASL_RESOURCE_NODE *Rnode; 418 UINT8 *VendorData; 419 UINT32 i; 420 421 422 /* Count the number of data bytes */ 423 424 InitializerOp = Info->DescriptorTypeOp->Asl.Child; 425 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); 426 427 for (i = 0; InitializerOp; i++) 428 { 429 if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 430 { 431 break; 432 } 433 InitializerOp = InitializerOp->Asl.Next; 434 } 435 436 InitializerOp = Info->DescriptorTypeOp->Asl.Child; 437 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); 438 Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_VENDOR_LARGE) + i); 439 440 Descriptor = Rnode->Buffer; 441 Descriptor->VendorLarge.DescriptorType = ACPI_RESOURCE_NAME_VENDOR_LARGE; 442 Descriptor->VendorLarge.ResourceLength = (UINT16) i; 443 444 /* Point to end-of-descriptor for vendor data */ 445 446 VendorData = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_LARGE_HEADER); 447 448 /* Process all child initialization nodes */ 449 450 for (i = 0; InitializerOp; i++) 451 { 452 if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 453 { 454 break; 455 } 456 457 VendorData[i] = (UINT8) InitializerOp->Asl.Value.Integer; 458 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); 459 } 460 461 return (Rnode); 462 } 463