1 /******************************************************************************* 2 * 3 * Module Name: rsmisc - Miscellaneous resource descriptors 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2011, 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 #define __RSMISC_C__ 45 46 #include "acpi.h" 47 #include "accommon.h" 48 #include "acresrc.h" 49 50 #define _COMPONENT ACPI_RESOURCES 51 ACPI_MODULE_NAME ("rsmisc") 52 53 54 #define INIT_RESOURCE_TYPE(i) i->ResourceOffset 55 #define INIT_RESOURCE_LENGTH(i) i->AmlOffset 56 #define INIT_TABLE_LENGTH(i) i->Value 57 58 #define COMPARE_OPCODE(i) i->ResourceOffset 59 #define COMPARE_TARGET(i) i->AmlOffset 60 #define COMPARE_VALUE(i) i->Value 61 62 63 /******************************************************************************* 64 * 65 * FUNCTION: AcpiRsConvertAmlToResource 66 * 67 * PARAMETERS: Resource - Pointer to the resource descriptor 68 * Aml - Where the AML descriptor is returned 69 * Info - Pointer to appropriate conversion table 70 * 71 * RETURN: Status 72 * 73 * DESCRIPTION: Convert an external AML resource descriptor to the corresponding 74 * internal resource descriptor 75 * 76 ******************************************************************************/ 77 78 ACPI_STATUS 79 AcpiRsConvertAmlToResource ( 80 ACPI_RESOURCE *Resource, 81 AML_RESOURCE *Aml, 82 ACPI_RSCONVERT_INFO *Info) 83 { 84 ACPI_RS_LENGTH AmlResourceLength; 85 void *Source; 86 void *Destination; 87 char *Target; 88 UINT8 Count; 89 UINT8 FlagsMode = FALSE; 90 UINT16 ItemCount = 0; 91 UINT16 Temp16 = 0; 92 93 94 ACPI_FUNCTION_TRACE (RsConvertAmlToResource); 95 96 97 if (((ACPI_SIZE) Resource) & 0x3) 98 { 99 /* Each internal resource struct is expected to be 32-bit aligned */ 100 101 ACPI_WARNING ((AE_INFO, 102 "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u", 103 Resource, Resource->Type, Resource->Length)); 104 } 105 106 /* Extract the resource Length field (does not include header length) */ 107 108 AmlResourceLength = AcpiUtGetResourceLength (Aml); 109 110 /* 111 * First table entry must be ACPI_RSC_INITxxx and must contain the 112 * table length (# of table entries) 113 */ 114 Count = INIT_TABLE_LENGTH (Info); 115 116 while (Count) 117 { 118 /* 119 * Source is the external AML byte stream buffer, 120 * destination is the internal resource descriptor 121 */ 122 Source = ACPI_ADD_PTR (void, Aml, Info->AmlOffset); 123 Destination = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset); 124 125 switch (Info->Opcode) 126 { 127 case ACPI_RSC_INITGET: 128 /* 129 * Get the resource type and the initial (minimum) length 130 */ 131 ACPI_MEMSET (Resource, 0, INIT_RESOURCE_LENGTH (Info)); 132 Resource->Type = INIT_RESOURCE_TYPE (Info); 133 Resource->Length = INIT_RESOURCE_LENGTH (Info); 134 break; 135 136 137 case ACPI_RSC_INITSET: 138 break; 139 140 141 case ACPI_RSC_FLAGINIT: 142 143 FlagsMode = TRUE; 144 break; 145 146 147 case ACPI_RSC_1BITFLAG: 148 /* 149 * Mask and shift the flag bit 150 */ 151 ACPI_SET8 (Destination) = (UINT8) 152 ((ACPI_GET8 (Source) >> Info->Value) & 0x01); 153 break; 154 155 156 case ACPI_RSC_2BITFLAG: 157 /* 158 * Mask and shift the flag bits 159 */ 160 ACPI_SET8 (Destination) = (UINT8) 161 ((ACPI_GET8 (Source) >> Info->Value) & 0x03); 162 break; 163 164 165 case ACPI_RSC_COUNT: 166 167 ItemCount = ACPI_GET8 (Source); 168 ACPI_SET8 (Destination) = (UINT8) ItemCount; 169 170 Resource->Length = Resource->Length + 171 (Info->Value * (ItemCount - 1)); 172 break; 173 174 175 case ACPI_RSC_COUNT16: 176 177 ItemCount = AmlResourceLength; 178 ACPI_SET16 (Destination) = ItemCount; 179 180 Resource->Length = Resource->Length + 181 (Info->Value * (ItemCount - 1)); 182 break; 183 184 185 case ACPI_RSC_LENGTH: 186 187 Resource->Length = Resource->Length + Info->Value; 188 break; 189 190 191 case ACPI_RSC_MOVE8: 192 case ACPI_RSC_MOVE16: 193 case ACPI_RSC_MOVE32: 194 case ACPI_RSC_MOVE64: 195 /* 196 * Raw data move. Use the Info value field unless ItemCount has 197 * been previously initialized via a COUNT opcode 198 */ 199 if (Info->Value) 200 { 201 ItemCount = Info->Value; 202 } 203 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode); 204 break; 205 206 207 case ACPI_RSC_SET8: 208 209 ACPI_MEMSET (Destination, Info->AmlOffset, Info->Value); 210 break; 211 212 213 case ACPI_RSC_DATA8: 214 215 Target = ACPI_ADD_PTR (char, Resource, Info->Value); 216 ACPI_MEMCPY (Destination, Source, ACPI_GET16 (Target)); 217 break; 218 219 220 case ACPI_RSC_ADDRESS: 221 /* 222 * Common handler for address descriptor flags 223 */ 224 if (!AcpiRsGetAddressCommon (Resource, Aml)) 225 { 226 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); 227 } 228 break; 229 230 231 case ACPI_RSC_SOURCE: 232 /* 233 * Optional ResourceSource (Index and String) 234 */ 235 Resource->Length += 236 AcpiRsGetResourceSource (AmlResourceLength, Info->Value, 237 Destination, Aml, NULL); 238 break; 239 240 241 case ACPI_RSC_SOURCEX: 242 /* 243 * Optional ResourceSource (Index and String). This is the more 244 * complicated case used by the Interrupt() macro 245 */ 246 Target = ACPI_ADD_PTR (char, Resource, Info->AmlOffset + (ItemCount * 4)); 247 248 Resource->Length += 249 AcpiRsGetResourceSource (AmlResourceLength, 250 (ACPI_RS_LENGTH) (((ItemCount - 1) * sizeof (UINT32)) + Info->Value), 251 Destination, Aml, Target); 252 break; 253 254 255 case ACPI_RSC_BITMASK: 256 /* 257 * 8-bit encoded bitmask (DMA macro) 258 */ 259 ItemCount = AcpiRsDecodeBitmask (ACPI_GET8 (Source), Destination); 260 if (ItemCount) 261 { 262 Resource->Length += (ItemCount - 1); 263 } 264 265 Target = ACPI_ADD_PTR (char, Resource, Info->Value); 266 ACPI_SET8 (Target) = (UINT8) ItemCount; 267 break; 268 269 270 case ACPI_RSC_BITMASK16: 271 /* 272 * 16-bit encoded bitmask (IRQ macro) 273 */ 274 ACPI_MOVE_16_TO_16 (&Temp16, Source); 275 276 ItemCount = AcpiRsDecodeBitmask (Temp16, Destination); 277 if (ItemCount) 278 { 279 Resource->Length += (ItemCount - 1); 280 } 281 282 Target = ACPI_ADD_PTR (char, Resource, Info->Value); 283 ACPI_SET8 (Target) = (UINT8) ItemCount; 284 break; 285 286 287 case ACPI_RSC_EXIT_NE: 288 /* 289 * Control - Exit conversion if not equal 290 */ 291 switch (Info->ResourceOffset) 292 { 293 case ACPI_RSC_COMPARE_AML_LENGTH: 294 if (AmlResourceLength != Info->Value) 295 { 296 goto Exit; 297 } 298 break; 299 300 case ACPI_RSC_COMPARE_VALUE: 301 if (ACPI_GET8 (Source) != Info->Value) 302 { 303 goto Exit; 304 } 305 break; 306 307 default: 308 309 ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode")); 310 return_ACPI_STATUS (AE_BAD_PARAMETER); 311 } 312 break; 313 314 315 default: 316 317 ACPI_ERROR ((AE_INFO, "Invalid conversion opcode")); 318 return_ACPI_STATUS (AE_BAD_PARAMETER); 319 } 320 321 Count--; 322 Info++; 323 } 324 325 Exit: 326 if (!FlagsMode) 327 { 328 /* Round the resource struct length up to the next boundary (32 or 64) */ 329 330 Resource->Length = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (Resource->Length); 331 } 332 return_ACPI_STATUS (AE_OK); 333 } 334 335 336 /******************************************************************************* 337 * 338 * FUNCTION: AcpiRsConvertResourceToAml 339 * 340 * PARAMETERS: Resource - Pointer to the resource descriptor 341 * Aml - Where the AML descriptor is returned 342 * Info - Pointer to appropriate conversion table 343 * 344 * RETURN: Status 345 * 346 * DESCRIPTION: Convert an internal resource descriptor to the corresponding 347 * external AML resource descriptor. 348 * 349 ******************************************************************************/ 350 351 ACPI_STATUS 352 AcpiRsConvertResourceToAml ( 353 ACPI_RESOURCE *Resource, 354 AML_RESOURCE *Aml, 355 ACPI_RSCONVERT_INFO *Info) 356 { 357 void *Source = NULL; 358 void *Destination; 359 ACPI_RSDESC_SIZE AmlLength = 0; 360 UINT8 Count; 361 UINT16 Temp16 = 0; 362 UINT16 ItemCount = 0; 363 364 365 ACPI_FUNCTION_TRACE (RsConvertResourceToAml); 366 367 368 /* 369 * First table entry must be ACPI_RSC_INITxxx and must contain the 370 * table length (# of table entries) 371 */ 372 Count = INIT_TABLE_LENGTH (Info); 373 374 while (Count) 375 { 376 /* 377 * Source is the internal resource descriptor, 378 * destination is the external AML byte stream buffer 379 */ 380 Source = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset); 381 Destination = ACPI_ADD_PTR (void, Aml, Info->AmlOffset); 382 383 switch (Info->Opcode) 384 { 385 case ACPI_RSC_INITSET: 386 387 ACPI_MEMSET (Aml, 0, INIT_RESOURCE_LENGTH (Info)); 388 AmlLength = INIT_RESOURCE_LENGTH (Info); 389 AcpiRsSetResourceHeader (INIT_RESOURCE_TYPE (Info), AmlLength, Aml); 390 break; 391 392 393 case ACPI_RSC_INITGET: 394 break; 395 396 397 case ACPI_RSC_FLAGINIT: 398 /* 399 * Clear the flag byte 400 */ 401 ACPI_SET8 (Destination) = 0; 402 break; 403 404 405 case ACPI_RSC_1BITFLAG: 406 /* 407 * Mask and shift the flag bit 408 */ 409 ACPI_SET8 (Destination) |= (UINT8) 410 ((ACPI_GET8 (Source) & 0x01) << Info->Value); 411 break; 412 413 414 case ACPI_RSC_2BITFLAG: 415 /* 416 * Mask and shift the flag bits 417 */ 418 ACPI_SET8 (Destination) |= (UINT8) 419 ((ACPI_GET8 (Source) & 0x03) << Info->Value); 420 break; 421 422 423 case ACPI_RSC_COUNT: 424 425 ItemCount = ACPI_GET8 (Source); 426 ACPI_SET8 (Destination) = (UINT8) ItemCount; 427 428 AmlLength = (UINT16) (AmlLength + (Info->Value * (ItemCount - 1))); 429 break; 430 431 432 case ACPI_RSC_COUNT16: 433 434 ItemCount = ACPI_GET16 (Source); 435 AmlLength = (UINT16) (AmlLength + ItemCount); 436 AcpiRsSetResourceLength (AmlLength, Aml); 437 break; 438 439 440 case ACPI_RSC_LENGTH: 441 442 AcpiRsSetResourceLength (Info->Value, Aml); 443 break; 444 445 446 case ACPI_RSC_MOVE8: 447 case ACPI_RSC_MOVE16: 448 case ACPI_RSC_MOVE32: 449 case ACPI_RSC_MOVE64: 450 451 if (Info->Value) 452 { 453 ItemCount = Info->Value; 454 } 455 AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode); 456 break; 457 458 459 case ACPI_RSC_ADDRESS: 460 461 /* Set the Resource Type, General Flags, and Type-Specific Flags */ 462 463 AcpiRsSetAddressCommon (Aml, Resource); 464 break; 465 466 467 case ACPI_RSC_SOURCEX: 468 /* 469 * Optional ResourceSource (Index and String) 470 */ 471 AmlLength = AcpiRsSetResourceSource ( 472 Aml, (ACPI_RS_LENGTH) AmlLength, Source); 473 AcpiRsSetResourceLength (AmlLength, Aml); 474 break; 475 476 477 case ACPI_RSC_SOURCE: 478 /* 479 * Optional ResourceSource (Index and String). This is the more 480 * complicated case used by the Interrupt() macro 481 */ 482 AmlLength = AcpiRsSetResourceSource (Aml, Info->Value, Source); 483 AcpiRsSetResourceLength (AmlLength, Aml); 484 break; 485 486 487 case ACPI_RSC_BITMASK: 488 /* 489 * 8-bit encoded bitmask (DMA macro) 490 */ 491 ACPI_SET8 (Destination) = (UINT8) 492 AcpiRsEncodeBitmask (Source, 493 *ACPI_ADD_PTR (UINT8, Resource, Info->Value)); 494 break; 495 496 497 case ACPI_RSC_BITMASK16: 498 /* 499 * 16-bit encoded bitmask (IRQ macro) 500 */ 501 Temp16 = AcpiRsEncodeBitmask (Source, 502 *ACPI_ADD_PTR (UINT8, Resource, Info->Value)); 503 ACPI_MOVE_16_TO_16 (Destination, &Temp16); 504 break; 505 506 507 case ACPI_RSC_EXIT_LE: 508 /* 509 * Control - Exit conversion if less than or equal 510 */ 511 if (ItemCount <= Info->Value) 512 { 513 goto Exit; 514 } 515 break; 516 517 518 case ACPI_RSC_EXIT_NE: 519 /* 520 * Control - Exit conversion if not equal 521 */ 522 switch (COMPARE_OPCODE (Info)) 523 { 524 case ACPI_RSC_COMPARE_VALUE: 525 526 if (*ACPI_ADD_PTR (UINT8, Resource, 527 COMPARE_TARGET (Info)) != COMPARE_VALUE (Info)) 528 { 529 goto Exit; 530 } 531 break; 532 533 default: 534 535 ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode")); 536 return_ACPI_STATUS (AE_BAD_PARAMETER); 537 } 538 break; 539 540 541 case ACPI_RSC_EXIT_EQ: 542 /* 543 * Control - Exit conversion if equal 544 */ 545 if (*ACPI_ADD_PTR (UINT8, Resource, 546 COMPARE_TARGET (Info)) == COMPARE_VALUE (Info)) 547 { 548 goto Exit; 549 } 550 break; 551 552 553 default: 554 555 ACPI_ERROR ((AE_INFO, "Invalid conversion opcode")); 556 return_ACPI_STATUS (AE_BAD_PARAMETER); 557 } 558 559 Count--; 560 Info++; 561 } 562 563 Exit: 564 return_ACPI_STATUS (AE_OK); 565 } 566 567 568 #if 0 569 /* Previous resource validations */ 570 571 if (Aml->ExtAddress64.RevisionID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) 572 { 573 return_ACPI_STATUS (AE_SUPPORT); 574 } 575 576 if (Resource->Data.StartDpf.PerformanceRobustness >= 3) 577 { 578 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE); 579 } 580 581 if (((Aml->Irq.Flags & 0x09) == 0x00) || 582 ((Aml->Irq.Flags & 0x09) == 0x09)) 583 { 584 /* 585 * Only [ActiveHigh, EdgeSensitive] or [ActiveLow, LevelSensitive] 586 * polarity/trigger interrupts are allowed (ACPI spec, section 587 * "IRQ Format"), so 0x00 and 0x09 are illegal. 588 */ 589 ACPI_ERROR ((AE_INFO, 590 "Invalid interrupt polarity/trigger in resource list, 0x%X", 591 Aml->Irq.Flags)); 592 return_ACPI_STATUS (AE_BAD_DATA); 593 } 594 595 Resource->Data.ExtendedIrq.InterruptCount = Temp8; 596 if (Temp8 < 1) 597 { 598 /* Must have at least one IRQ */ 599 600 return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); 601 } 602 603 if (Resource->Data.Dma.Transfer == 0x03) 604 { 605 ACPI_ERROR ((AE_INFO, 606 "Invalid DMA.Transfer preference (3)")); 607 return_ACPI_STATUS (AE_BAD_DATA); 608 } 609 #endif 610 611