1 /******************************************************************************* 2 * 3 * Module Name: utresrc - Resource managment utilities 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 45 #define __UTRESRC_C__ 46 47 #include "acpi.h" 48 #include "accommon.h" 49 #include "amlresrc.h" 50 51 52 #define _COMPONENT ACPI_UTILITIES 53 ACPI_MODULE_NAME ("utresrc") 54 55 56 #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) 57 58 /* 59 * Strings used to decode resource descriptors. 60 * Used by both the disasssembler and the debugger resource dump routines 61 */ 62 const char *AcpiGbl_BmDecode[] = 63 { 64 "NotBusMaster", 65 "BusMaster" 66 }; 67 68 const char *AcpiGbl_ConfigDecode[] = 69 { 70 "0 - Good Configuration", 71 "1 - Acceptable Configuration", 72 "2 - Suboptimal Configuration", 73 "3 - ***Invalid Configuration***", 74 }; 75 76 const char *AcpiGbl_ConsumeDecode[] = 77 { 78 "ResourceProducer", 79 "ResourceConsumer" 80 }; 81 82 const char *AcpiGbl_DecDecode[] = 83 { 84 "PosDecode", 85 "SubDecode" 86 }; 87 88 const char *AcpiGbl_HeDecode[] = 89 { 90 "Level", 91 "Edge" 92 }; 93 94 const char *AcpiGbl_IoDecode[] = 95 { 96 "Decode10", 97 "Decode16" 98 }; 99 100 const char *AcpiGbl_LlDecode[] = 101 { 102 "ActiveHigh", 103 "ActiveLow" 104 }; 105 106 const char *AcpiGbl_MaxDecode[] = 107 { 108 "MaxNotFixed", 109 "MaxFixed" 110 }; 111 112 const char *AcpiGbl_MemDecode[] = 113 { 114 "NonCacheable", 115 "Cacheable", 116 "WriteCombining", 117 "Prefetchable" 118 }; 119 120 const char *AcpiGbl_MinDecode[] = 121 { 122 "MinNotFixed", 123 "MinFixed" 124 }; 125 126 const char *AcpiGbl_MtpDecode[] = 127 { 128 "AddressRangeMemory", 129 "AddressRangeReserved", 130 "AddressRangeACPI", 131 "AddressRangeNVS" 132 }; 133 134 const char *AcpiGbl_RngDecode[] = 135 { 136 "InvalidRanges", 137 "NonISAOnlyRanges", 138 "ISAOnlyRanges", 139 "EntireRange" 140 }; 141 142 const char *AcpiGbl_RwDecode[] = 143 { 144 "ReadOnly", 145 "ReadWrite" 146 }; 147 148 const char *AcpiGbl_ShrDecode[] = 149 { 150 "Exclusive", 151 "Shared" 152 }; 153 154 const char *AcpiGbl_SizDecode[] = 155 { 156 "Transfer8", 157 "Transfer8_16", 158 "Transfer16", 159 "InvalidSize" 160 }; 161 162 const char *AcpiGbl_TrsDecode[] = 163 { 164 "DenseTranslation", 165 "SparseTranslation" 166 }; 167 168 const char *AcpiGbl_TtpDecode[] = 169 { 170 "TypeStatic", 171 "TypeTranslation" 172 }; 173 174 const char *AcpiGbl_TypDecode[] = 175 { 176 "Compatibility", 177 "TypeA", 178 "TypeB", 179 "TypeF" 180 }; 181 182 #endif 183 184 185 /* 186 * Base sizes of the raw AML resource descriptors, indexed by resource type. 187 * Zero indicates a reserved (and therefore invalid) resource type. 188 */ 189 const UINT8 AcpiGbl_ResourceAmlSizes[] = 190 { 191 /* Small descriptors */ 192 193 0, 194 0, 195 0, 196 0, 197 ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ), 198 ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA), 199 ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT), 200 ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT), 201 ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO), 202 ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO), 203 0, 204 0, 205 0, 206 0, 207 ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL), 208 ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG), 209 210 /* Large descriptors */ 211 212 0, 213 ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24), 214 ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER), 215 0, 216 ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE), 217 ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32), 218 ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32), 219 ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32), 220 ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16), 221 ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ), 222 ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64), 223 ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64) 224 }; 225 226 227 /* 228 * Resource types, used to validate the resource length field. 229 * The length of fixed-length types must match exactly, variable 230 * lengths must meet the minimum required length, etc. 231 * Zero indicates a reserved (and therefore invalid) resource type. 232 */ 233 static const UINT8 AcpiGbl_ResourceTypes[] = 234 { 235 /* Small descriptors */ 236 237 0, 238 0, 239 0, 240 0, 241 ACPI_SMALL_VARIABLE_LENGTH, 242 ACPI_FIXED_LENGTH, 243 ACPI_SMALL_VARIABLE_LENGTH, 244 ACPI_FIXED_LENGTH, 245 ACPI_FIXED_LENGTH, 246 ACPI_FIXED_LENGTH, 247 0, 248 0, 249 0, 250 0, 251 ACPI_VARIABLE_LENGTH, 252 ACPI_FIXED_LENGTH, 253 254 /* Large descriptors */ 255 256 0, 257 ACPI_FIXED_LENGTH, 258 ACPI_FIXED_LENGTH, 259 0, 260 ACPI_VARIABLE_LENGTH, 261 ACPI_FIXED_LENGTH, 262 ACPI_FIXED_LENGTH, 263 ACPI_VARIABLE_LENGTH, 264 ACPI_VARIABLE_LENGTH, 265 ACPI_VARIABLE_LENGTH, 266 ACPI_VARIABLE_LENGTH, 267 ACPI_FIXED_LENGTH 268 }; 269 270 271 /******************************************************************************* 272 * 273 * FUNCTION: AcpiUtWalkAmlResources 274 * 275 * PARAMETERS: Aml - Pointer to the raw AML resource template 276 * AmlLength - Length of the entire template 277 * UserFunction - Called once for each descriptor found. If 278 * NULL, a pointer to the EndTag is returned 279 * Context - Passed to UserFunction 280 * 281 * RETURN: Status 282 * 283 * DESCRIPTION: Walk a raw AML resource list(buffer). User function called 284 * once for each resource found. 285 * 286 ******************************************************************************/ 287 288 ACPI_STATUS 289 AcpiUtWalkAmlResources ( 290 UINT8 *Aml, 291 ACPI_SIZE AmlLength, 292 ACPI_WALK_AML_CALLBACK UserFunction, 293 void *Context) 294 { 295 ACPI_STATUS Status; 296 UINT8 *EndAml; 297 UINT8 ResourceIndex; 298 UINT32 Length; 299 UINT32 Offset = 0; 300 301 302 ACPI_FUNCTION_TRACE (UtWalkAmlResources); 303 304 305 /* The absolute minimum resource template is one EndTag descriptor */ 306 307 if (AmlLength < sizeof (AML_RESOURCE_END_TAG)) 308 { 309 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 310 } 311 312 /* Point to the end of the resource template buffer */ 313 314 EndAml = Aml + AmlLength; 315 316 /* Walk the byte list, abort on any invalid descriptor type or length */ 317 318 while (Aml < EndAml) 319 { 320 /* Validate the Resource Type and Resource Length */ 321 322 Status = AcpiUtValidateResource (Aml, &ResourceIndex); 323 if (ACPI_FAILURE (Status)) 324 { 325 return_ACPI_STATUS (Status); 326 } 327 328 /* Get the length of this descriptor */ 329 330 Length = AcpiUtGetDescriptorLength (Aml); 331 332 /* Invoke the user function */ 333 334 if (UserFunction) 335 { 336 Status = UserFunction (Aml, Length, Offset, ResourceIndex, Context); 337 if (ACPI_FAILURE (Status)) 338 { 339 return (Status); 340 } 341 } 342 343 /* An EndTag descriptor terminates this resource template */ 344 345 if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_END_TAG) 346 { 347 /* 348 * There must be at least one more byte in the buffer for 349 * the 2nd byte of the EndTag 350 */ 351 if ((Aml + 1) >= EndAml) 352 { 353 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 354 } 355 356 /* Return the pointer to the EndTag if requested */ 357 358 if (!UserFunction) 359 { 360 *(void **) Context = Aml; 361 } 362 363 /* Normal exit */ 364 365 return_ACPI_STATUS (AE_OK); 366 } 367 368 Aml += Length; 369 Offset += Length; 370 } 371 372 /* Did not find an EndTag descriptor */ 373 374 return (AE_AML_NO_RESOURCE_END_TAG); 375 } 376 377 378 /******************************************************************************* 379 * 380 * FUNCTION: AcpiUtValidateResource 381 * 382 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 383 * ReturnIndex - Where the resource index is returned. NULL 384 * if the index is not required. 385 * 386 * RETURN: Status, and optionally the Index into the global resource tables 387 * 388 * DESCRIPTION: Validate an AML resource descriptor by checking the Resource 389 * Type and Resource Length. Returns an index into the global 390 * resource information/dispatch tables for later use. 391 * 392 ******************************************************************************/ 393 394 ACPI_STATUS 395 AcpiUtValidateResource ( 396 void *Aml, 397 UINT8 *ReturnIndex) 398 { 399 UINT8 ResourceType; 400 UINT8 ResourceIndex; 401 ACPI_RS_LENGTH ResourceLength; 402 ACPI_RS_LENGTH MinimumResourceLength; 403 404 405 ACPI_FUNCTION_ENTRY (); 406 407 408 /* 409 * 1) Validate the ResourceType field (Byte 0) 410 */ 411 ResourceType = ACPI_GET8 (Aml); 412 413 /* 414 * Byte 0 contains the descriptor name (Resource Type) 415 * Examine the large/small bit in the resource header 416 */ 417 if (ResourceType & ACPI_RESOURCE_NAME_LARGE) 418 { 419 /* Verify the large resource type (name) against the max */ 420 421 if (ResourceType > ACPI_RESOURCE_NAME_LARGE_MAX) 422 { 423 return (AE_AML_INVALID_RESOURCE_TYPE); 424 } 425 426 /* 427 * Large Resource Type -- bits 6:0 contain the name 428 * Translate range 0x80-0x8B to index range 0x10-0x1B 429 */ 430 ResourceIndex = (UINT8) (ResourceType - 0x70); 431 } 432 else 433 { 434 /* 435 * Small Resource Type -- bits 6:3 contain the name 436 * Shift range to index range 0x00-0x0F 437 */ 438 ResourceIndex = (UINT8) 439 ((ResourceType & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); 440 } 441 442 /* Check validity of the resource type, zero indicates name is invalid */ 443 444 if (!AcpiGbl_ResourceTypes[ResourceIndex]) 445 { 446 return (AE_AML_INVALID_RESOURCE_TYPE); 447 } 448 449 450 /* 451 * 2) Validate the ResourceLength field. This ensures that the length 452 * is at least reasonable, and guarantees that it is non-zero. 453 */ 454 ResourceLength = AcpiUtGetResourceLength (Aml); 455 MinimumResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex]; 456 457 /* Validate based upon the type of resource - fixed length or variable */ 458 459 switch (AcpiGbl_ResourceTypes[ResourceIndex]) 460 { 461 case ACPI_FIXED_LENGTH: 462 463 /* Fixed length resource, length must match exactly */ 464 465 if (ResourceLength != MinimumResourceLength) 466 { 467 return (AE_AML_BAD_RESOURCE_LENGTH); 468 } 469 break; 470 471 case ACPI_VARIABLE_LENGTH: 472 473 /* Variable length resource, length must be at least the minimum */ 474 475 if (ResourceLength < MinimumResourceLength) 476 { 477 return (AE_AML_BAD_RESOURCE_LENGTH); 478 } 479 break; 480 481 case ACPI_SMALL_VARIABLE_LENGTH: 482 483 /* Small variable length resource, length can be (Min) or (Min-1) */ 484 485 if ((ResourceLength > MinimumResourceLength) || 486 (ResourceLength < (MinimumResourceLength - 1))) 487 { 488 return (AE_AML_BAD_RESOURCE_LENGTH); 489 } 490 break; 491 492 default: 493 494 /* Shouldn't happen (because of validation earlier), but be sure */ 495 496 return (AE_AML_INVALID_RESOURCE_TYPE); 497 } 498 499 /* Optionally return the resource table index */ 500 501 if (ReturnIndex) 502 { 503 *ReturnIndex = ResourceIndex; 504 } 505 506 return (AE_OK); 507 } 508 509 510 /******************************************************************************* 511 * 512 * FUNCTION: AcpiUtGetResourceType 513 * 514 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 515 * 516 * RETURN: The Resource Type with no extraneous bits (except the 517 * Large/Small descriptor bit -- this is left alone) 518 * 519 * DESCRIPTION: Extract the Resource Type/Name from the first byte of 520 * a resource descriptor. 521 * 522 ******************************************************************************/ 523 524 UINT8 525 AcpiUtGetResourceType ( 526 void *Aml) 527 { 528 ACPI_FUNCTION_ENTRY (); 529 530 531 /* 532 * Byte 0 contains the descriptor name (Resource Type) 533 * Examine the large/small bit in the resource header 534 */ 535 if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) 536 { 537 /* Large Resource Type -- bits 6:0 contain the name */ 538 539 return (ACPI_GET8 (Aml)); 540 } 541 else 542 { 543 /* Small Resource Type -- bits 6:3 contain the name */ 544 545 return ((UINT8) (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); 546 } 547 } 548 549 550 /******************************************************************************* 551 * 552 * FUNCTION: AcpiUtGetResourceLength 553 * 554 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 555 * 556 * RETURN: Byte Length 557 * 558 * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By 559 * definition, this does not include the size of the descriptor 560 * header or the length field itself. 561 * 562 ******************************************************************************/ 563 564 UINT16 565 AcpiUtGetResourceLength ( 566 void *Aml) 567 { 568 ACPI_RS_LENGTH ResourceLength; 569 570 571 ACPI_FUNCTION_ENTRY (); 572 573 574 /* 575 * Byte 0 contains the descriptor name (Resource Type) 576 * Examine the large/small bit in the resource header 577 */ 578 if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) 579 { 580 /* Large Resource type -- bytes 1-2 contain the 16-bit length */ 581 582 ACPI_MOVE_16_TO_16 (&ResourceLength, ACPI_ADD_PTR (UINT8, Aml, 1)); 583 584 } 585 else 586 { 587 /* Small Resource type -- bits 2:0 of byte 0 contain the length */ 588 589 ResourceLength = (UINT16) (ACPI_GET8 (Aml) & 590 ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); 591 } 592 593 return (ResourceLength); 594 } 595 596 597 /******************************************************************************* 598 * 599 * FUNCTION: AcpiUtGetResourceHeaderLength 600 * 601 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 602 * 603 * RETURN: Length of the AML header (depends on large/small descriptor) 604 * 605 * DESCRIPTION: Get the length of the header for this resource. 606 * 607 ******************************************************************************/ 608 609 UINT8 610 AcpiUtGetResourceHeaderLength ( 611 void *Aml) 612 { 613 ACPI_FUNCTION_ENTRY (); 614 615 616 /* Examine the large/small bit in the resource header */ 617 618 if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) 619 { 620 return (sizeof (AML_RESOURCE_LARGE_HEADER)); 621 } 622 else 623 { 624 return (sizeof (AML_RESOURCE_SMALL_HEADER)); 625 } 626 } 627 628 629 /******************************************************************************* 630 * 631 * FUNCTION: AcpiUtGetDescriptorLength 632 * 633 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 634 * 635 * RETURN: Byte length 636 * 637 * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the 638 * length of the descriptor header and the length field itself. 639 * Used to walk descriptor lists. 640 * 641 ******************************************************************************/ 642 643 UINT32 644 AcpiUtGetDescriptorLength ( 645 void *Aml) 646 { 647 ACPI_FUNCTION_ENTRY (); 648 649 650 /* 651 * Get the Resource Length (does not include header length) and add 652 * the header length (depends on if this is a small or large resource) 653 */ 654 return (AcpiUtGetResourceLength (Aml) + 655 AcpiUtGetResourceHeaderLength (Aml)); 656 } 657 658 659 /******************************************************************************* 660 * 661 * FUNCTION: AcpiUtGetResourceEndTag 662 * 663 * PARAMETERS: ObjDesc - The resource template buffer object 664 * EndTag - Where the pointer to the EndTag is returned 665 * 666 * RETURN: Status, pointer to the end tag 667 * 668 * DESCRIPTION: Find the EndTag resource descriptor in an AML resource template 669 * Note: allows a buffer length of zero. 670 * 671 ******************************************************************************/ 672 673 ACPI_STATUS 674 AcpiUtGetResourceEndTag ( 675 ACPI_OPERAND_OBJECT *ObjDesc, 676 UINT8 **EndTag) 677 { 678 ACPI_STATUS Status; 679 680 681 ACPI_FUNCTION_TRACE (UtGetResourceEndTag); 682 683 684 /* Allow a buffer length of zero */ 685 686 if (!ObjDesc->Buffer.Length) 687 { 688 *EndTag = ObjDesc->Buffer.Pointer; 689 return_ACPI_STATUS (AE_OK); 690 } 691 692 /* Validate the template and get a pointer to the EndTag */ 693 694 Status = AcpiUtWalkAmlResources (ObjDesc->Buffer.Pointer, 695 ObjDesc->Buffer.Length, NULL, EndTag); 696 697 return_ACPI_STATUS (Status); 698 } 699 700