utresrc.c revision 217365
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 <contrib/dev/acpica/include/acpi.h> 48#include <contrib/dev/acpica/include/accommon.h> 49#include <contrib/dev/acpica/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 */ 62const char *AcpiGbl_BmDecode[] = 63{ 64 "NotBusMaster", 65 "BusMaster" 66}; 67 68const char *AcpiGbl_ConfigDecode[] = 69{ 70 "0 - Good Configuration", 71 "1 - Acceptable Configuration", 72 "2 - Suboptimal Configuration", 73 "3 - ***Invalid Configuration***", 74}; 75 76const char *AcpiGbl_ConsumeDecode[] = 77{ 78 "ResourceProducer", 79 "ResourceConsumer" 80}; 81 82const char *AcpiGbl_DecDecode[] = 83{ 84 "PosDecode", 85 "SubDecode" 86}; 87 88const char *AcpiGbl_HeDecode[] = 89{ 90 "Level", 91 "Edge" 92}; 93 94const char *AcpiGbl_IoDecode[] = 95{ 96 "Decode10", 97 "Decode16" 98}; 99 100const char *AcpiGbl_LlDecode[] = 101{ 102 "ActiveHigh", 103 "ActiveLow" 104}; 105 106const char *AcpiGbl_MaxDecode[] = 107{ 108 "MaxNotFixed", 109 "MaxFixed" 110}; 111 112const char *AcpiGbl_MemDecode[] = 113{ 114 "NonCacheable", 115 "Cacheable", 116 "WriteCombining", 117 "Prefetchable" 118}; 119 120const char *AcpiGbl_MinDecode[] = 121{ 122 "MinNotFixed", 123 "MinFixed" 124}; 125 126const char *AcpiGbl_MtpDecode[] = 127{ 128 "AddressRangeMemory", 129 "AddressRangeReserved", 130 "AddressRangeACPI", 131 "AddressRangeNVS" 132}; 133 134const char *AcpiGbl_RngDecode[] = 135{ 136 "InvalidRanges", 137 "NonISAOnlyRanges", 138 "ISAOnlyRanges", 139 "EntireRange" 140}; 141 142const char *AcpiGbl_RwDecode[] = 143{ 144 "ReadOnly", 145 "ReadWrite" 146}; 147 148const char *AcpiGbl_ShrDecode[] = 149{ 150 "Exclusive", 151 "Shared" 152}; 153 154const char *AcpiGbl_SizDecode[] = 155{ 156 "Transfer8", 157 "Transfer8_16", 158 "Transfer16", 159 "InvalidSize" 160}; 161 162const char *AcpiGbl_TrsDecode[] = 163{ 164 "DenseTranslation", 165 "SparseTranslation" 166}; 167 168const char *AcpiGbl_TtpDecode[] = 169{ 170 "TypeStatic", 171 "TypeTranslation" 172}; 173 174const 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 */ 189const 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 */ 233static 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 288ACPI_STATUS 289AcpiUtWalkAmlResources ( 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 394ACPI_STATUS 395AcpiUtValidateResource ( 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 524UINT8 525AcpiUtGetResourceType ( 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 564UINT16 565AcpiUtGetResourceLength ( 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 609UINT8 610AcpiUtGetResourceHeaderLength ( 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 643UINT32 644AcpiUtGetDescriptorLength ( 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 673ACPI_STATUS 674AcpiUtGetResourceEndTag ( 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 701