Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.26-rc1 615 lines 17 kB view raw
1/******************************************************************************* 2 * 3 * Module Name: utresrc - Resource management utilities 4 * 5 ******************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2008, 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 <acpi/acpi.h> 45#include <acpi/amlresrc.h> 46 47#define _COMPONENT ACPI_UTILITIES 48ACPI_MODULE_NAME("utresrc") 49#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) 50/* 51 * Strings used to decode resource descriptors. 52 * Used by both the disasssembler and the debugger resource dump routines 53 */ 54const char *acpi_gbl_bm_decode[] = { 55 "NotBusMaster", 56 "BusMaster" 57}; 58 59const char *acpi_gbl_config_decode[] = { 60 "0 - Good Configuration", 61 "1 - Acceptable Configuration", 62 "2 - Suboptimal Configuration", 63 "3 - ***Invalid Configuration***", 64}; 65 66const char *acpi_gbl_consume_decode[] = { 67 "ResourceProducer", 68 "ResourceConsumer" 69}; 70 71const char *acpi_gbl_dec_decode[] = { 72 "PosDecode", 73 "SubDecode" 74}; 75 76const char *acpi_gbl_he_decode[] = { 77 "Level", 78 "Edge" 79}; 80 81const char *acpi_gbl_io_decode[] = { 82 "Decode10", 83 "Decode16" 84}; 85 86const char *acpi_gbl_ll_decode[] = { 87 "ActiveHigh", 88 "ActiveLow" 89}; 90 91const char *acpi_gbl_max_decode[] = { 92 "MaxNotFixed", 93 "MaxFixed" 94}; 95 96const char *acpi_gbl_mem_decode[] = { 97 "NonCacheable", 98 "Cacheable", 99 "WriteCombining", 100 "Prefetchable" 101}; 102 103const char *acpi_gbl_min_decode[] = { 104 "MinNotFixed", 105 "MinFixed" 106}; 107 108const char *acpi_gbl_mtp_decode[] = { 109 "AddressRangeMemory", 110 "AddressRangeReserved", 111 "AddressRangeACPI", 112 "AddressRangeNVS" 113}; 114 115const char *acpi_gbl_rng_decode[] = { 116 "InvalidRanges", 117 "NonISAOnlyRanges", 118 "ISAOnlyRanges", 119 "EntireRange" 120}; 121 122const char *acpi_gbl_rw_decode[] = { 123 "ReadOnly", 124 "ReadWrite" 125}; 126 127const char *acpi_gbl_shr_decode[] = { 128 "Exclusive", 129 "Shared" 130}; 131 132const char *acpi_gbl_siz_decode[] = { 133 "Transfer8", 134 "Transfer8_16", 135 "Transfer16", 136 "InvalidSize" 137}; 138 139const char *acpi_gbl_trs_decode[] = { 140 "DenseTranslation", 141 "SparseTranslation" 142}; 143 144const char *acpi_gbl_ttp_decode[] = { 145 "TypeStatic", 146 "TypeTranslation" 147}; 148 149const char *acpi_gbl_typ_decode[] = { 150 "Compatibility", 151 "TypeA", 152 "TypeB", 153 "TypeF" 154}; 155 156#endif 157 158/* 159 * Base sizes of the raw AML resource descriptors, indexed by resource type. 160 * Zero indicates a reserved (and therefore invalid) resource type. 161 */ 162const u8 acpi_gbl_resource_aml_sizes[] = { 163 /* Small descriptors */ 164 165 0, 166 0, 167 0, 168 0, 169 ACPI_AML_SIZE_SMALL(struct aml_resource_irq), 170 ACPI_AML_SIZE_SMALL(struct aml_resource_dma), 171 ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent), 172 ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent), 173 ACPI_AML_SIZE_SMALL(struct aml_resource_io), 174 ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io), 175 0, 176 0, 177 0, 178 0, 179 ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small), 180 ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag), 181 182 /* Large descriptors */ 183 184 0, 185 ACPI_AML_SIZE_LARGE(struct aml_resource_memory24), 186 ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register), 187 0, 188 ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large), 189 ACPI_AML_SIZE_LARGE(struct aml_resource_memory32), 190 ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32), 191 ACPI_AML_SIZE_LARGE(struct aml_resource_address32), 192 ACPI_AML_SIZE_LARGE(struct aml_resource_address16), 193 ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq), 194 ACPI_AML_SIZE_LARGE(struct aml_resource_address64), 195 ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64) 196}; 197 198/* 199 * Resource types, used to validate the resource length field. 200 * The length of fixed-length types must match exactly, variable 201 * lengths must meet the minimum required length, etc. 202 * Zero indicates a reserved (and therefore invalid) resource type. 203 */ 204static const u8 acpi_gbl_resource_types[] = { 205 /* Small descriptors */ 206 207 0, 208 0, 209 0, 210 0, 211 ACPI_SMALL_VARIABLE_LENGTH, 212 ACPI_FIXED_LENGTH, 213 ACPI_SMALL_VARIABLE_LENGTH, 214 ACPI_FIXED_LENGTH, 215 ACPI_FIXED_LENGTH, 216 ACPI_FIXED_LENGTH, 217 0, 218 0, 219 0, 220 0, 221 ACPI_VARIABLE_LENGTH, 222 ACPI_FIXED_LENGTH, 223 224 /* Large descriptors */ 225 226 0, 227 ACPI_FIXED_LENGTH, 228 ACPI_FIXED_LENGTH, 229 0, 230 ACPI_VARIABLE_LENGTH, 231 ACPI_FIXED_LENGTH, 232 ACPI_FIXED_LENGTH, 233 ACPI_VARIABLE_LENGTH, 234 ACPI_VARIABLE_LENGTH, 235 ACPI_VARIABLE_LENGTH, 236 ACPI_VARIABLE_LENGTH, 237 ACPI_FIXED_LENGTH 238}; 239 240/******************************************************************************* 241 * 242 * FUNCTION: acpi_ut_walk_aml_resources 243 * 244 * PARAMETERS: Aml - Pointer to the raw AML resource template 245 * aml_length - Length of the entire template 246 * user_function - Called once for each descriptor found. If 247 * NULL, a pointer to the end_tag is returned 248 * Context - Passed to user_function 249 * 250 * RETURN: Status 251 * 252 * DESCRIPTION: Walk a raw AML resource list(buffer). User function called 253 * once for each resource found. 254 * 255 ******************************************************************************/ 256 257acpi_status 258acpi_ut_walk_aml_resources(u8 * aml, 259 acpi_size aml_length, 260 acpi_walk_aml_callback user_function, void **context) 261{ 262 acpi_status status; 263 u8 *end_aml; 264 u8 resource_index; 265 u32 length; 266 u32 offset = 0; 267 268 ACPI_FUNCTION_TRACE(ut_walk_aml_resources); 269 270 /* The absolute minimum resource template is one end_tag descriptor */ 271 272 if (aml_length < sizeof(struct aml_resource_end_tag)) { 273 return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); 274 } 275 276 /* Point to the end of the resource template buffer */ 277 278 end_aml = aml + aml_length; 279 280 /* Walk the byte list, abort on any invalid descriptor type or length */ 281 282 while (aml < end_aml) { 283 284 /* Validate the Resource Type and Resource Length */ 285 286 status = acpi_ut_validate_resource(aml, &resource_index); 287 if (ACPI_FAILURE(status)) { 288 return_ACPI_STATUS(status); 289 } 290 291 /* Get the length of this descriptor */ 292 293 length = acpi_ut_get_descriptor_length(aml); 294 295 /* Invoke the user function */ 296 297 if (user_function) { 298 status = 299 user_function(aml, length, offset, resource_index, 300 context); 301 if (ACPI_FAILURE(status)) { 302 return (status); 303 } 304 } 305 306 /* An end_tag descriptor terminates this resource template */ 307 308 if (acpi_ut_get_resource_type(aml) == 309 ACPI_RESOURCE_NAME_END_TAG) { 310 /* 311 * There must be at least one more byte in the buffer for 312 * the 2nd byte of the end_tag 313 */ 314 if ((aml + 1) >= end_aml) { 315 return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); 316 } 317 318 /* Return the pointer to the end_tag if requested */ 319 320 if (!user_function) { 321 *context = aml; 322 } 323 324 /* Normal exit */ 325 326 return_ACPI_STATUS(AE_OK); 327 } 328 329 aml += length; 330 offset += length; 331 } 332 333 /* Did not find an end_tag descriptor */ 334 335 return (AE_AML_NO_RESOURCE_END_TAG); 336} 337 338/******************************************************************************* 339 * 340 * FUNCTION: acpi_ut_validate_resource 341 * 342 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 343 * return_index - Where the resource index is returned. NULL 344 * if the index is not required. 345 * 346 * RETURN: Status, and optionally the Index into the global resource tables 347 * 348 * DESCRIPTION: Validate an AML resource descriptor by checking the Resource 349 * Type and Resource Length. Returns an index into the global 350 * resource information/dispatch tables for later use. 351 * 352 ******************************************************************************/ 353 354acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) 355{ 356 u8 resource_type; 357 u8 resource_index; 358 acpi_rs_length resource_length; 359 acpi_rs_length minimum_resource_length; 360 361 ACPI_FUNCTION_ENTRY(); 362 363 /* 364 * 1) Validate the resource_type field (Byte 0) 365 */ 366 resource_type = ACPI_GET8(aml); 367 368 /* 369 * Byte 0 contains the descriptor name (Resource Type) 370 * Examine the large/small bit in the resource header 371 */ 372 if (resource_type & ACPI_RESOURCE_NAME_LARGE) { 373 374 /* Verify the large resource type (name) against the max */ 375 376 if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { 377 return (AE_AML_INVALID_RESOURCE_TYPE); 378 } 379 380 /* 381 * Large Resource Type -- bits 6:0 contain the name 382 * Translate range 0x80-0x8B to index range 0x10-0x1B 383 */ 384 resource_index = (u8) (resource_type - 0x70); 385 } else { 386 /* 387 * Small Resource Type -- bits 6:3 contain the name 388 * Shift range to index range 0x00-0x0F 389 */ 390 resource_index = (u8) 391 ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); 392 } 393 394 /* Check validity of the resource type, zero indicates name is invalid */ 395 396 if (!acpi_gbl_resource_types[resource_index]) { 397 return (AE_AML_INVALID_RESOURCE_TYPE); 398 } 399 400 /* 401 * 2) Validate the resource_length field. This ensures that the length 402 * is at least reasonable, and guarantees that it is non-zero. 403 */ 404 resource_length = acpi_ut_get_resource_length(aml); 405 minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index]; 406 407 /* Validate based upon the type of resource - fixed length or variable */ 408 409 switch (acpi_gbl_resource_types[resource_index]) { 410 case ACPI_FIXED_LENGTH: 411 412 /* Fixed length resource, length must match exactly */ 413 414 if (resource_length != minimum_resource_length) { 415 return (AE_AML_BAD_RESOURCE_LENGTH); 416 } 417 break; 418 419 case ACPI_VARIABLE_LENGTH: 420 421 /* Variable length resource, length must be at least the minimum */ 422 423 if (resource_length < minimum_resource_length) { 424 return (AE_AML_BAD_RESOURCE_LENGTH); 425 } 426 break; 427 428 case ACPI_SMALL_VARIABLE_LENGTH: 429 430 /* Small variable length resource, length can be (Min) or (Min-1) */ 431 432 if ((resource_length > minimum_resource_length) || 433 (resource_length < (minimum_resource_length - 1))) { 434 return (AE_AML_BAD_RESOURCE_LENGTH); 435 } 436 break; 437 438 default: 439 440 /* Shouldn't happen (because of validation earlier), but be sure */ 441 442 return (AE_AML_INVALID_RESOURCE_TYPE); 443 } 444 445 /* Optionally return the resource table index */ 446 447 if (return_index) { 448 *return_index = resource_index; 449 } 450 451 return (AE_OK); 452} 453 454/******************************************************************************* 455 * 456 * FUNCTION: acpi_ut_get_resource_type 457 * 458 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 459 * 460 * RETURN: The Resource Type with no extraneous bits (except the 461 * Large/Small descriptor bit -- this is left alone) 462 * 463 * DESCRIPTION: Extract the Resource Type/Name from the first byte of 464 * a resource descriptor. 465 * 466 ******************************************************************************/ 467 468u8 acpi_ut_get_resource_type(void *aml) 469{ 470 ACPI_FUNCTION_ENTRY(); 471 472 /* 473 * Byte 0 contains the descriptor name (Resource Type) 474 * Examine the large/small bit in the resource header 475 */ 476 if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { 477 478 /* Large Resource Type -- bits 6:0 contain the name */ 479 480 return (ACPI_GET8(aml)); 481 } else { 482 /* Small Resource Type -- bits 6:3 contain the name */ 483 484 return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); 485 } 486} 487 488/******************************************************************************* 489 * 490 * FUNCTION: acpi_ut_get_resource_length 491 * 492 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 493 * 494 * RETURN: Byte Length 495 * 496 * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By 497 * definition, this does not include the size of the descriptor 498 * header or the length field itself. 499 * 500 ******************************************************************************/ 501 502u16 acpi_ut_get_resource_length(void *aml) 503{ 504 acpi_rs_length resource_length; 505 506 ACPI_FUNCTION_ENTRY(); 507 508 /* 509 * Byte 0 contains the descriptor name (Resource Type) 510 * Examine the large/small bit in the resource header 511 */ 512 if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { 513 514 /* Large Resource type -- bytes 1-2 contain the 16-bit length */ 515 516 ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1)); 517 518 } else { 519 /* Small Resource type -- bits 2:0 of byte 0 contain the length */ 520 521 resource_length = (u16) (ACPI_GET8(aml) & 522 ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); 523 } 524 525 return (resource_length); 526} 527 528/******************************************************************************* 529 * 530 * FUNCTION: acpi_ut_get_resource_header_length 531 * 532 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 533 * 534 * RETURN: Length of the AML header (depends on large/small descriptor) 535 * 536 * DESCRIPTION: Get the length of the header for this resource. 537 * 538 ******************************************************************************/ 539 540u8 acpi_ut_get_resource_header_length(void *aml) 541{ 542 ACPI_FUNCTION_ENTRY(); 543 544 /* Examine the large/small bit in the resource header */ 545 546 if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { 547 return (sizeof(struct aml_resource_large_header)); 548 } else { 549 return (sizeof(struct aml_resource_small_header)); 550 } 551} 552 553/******************************************************************************* 554 * 555 * FUNCTION: acpi_ut_get_descriptor_length 556 * 557 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor 558 * 559 * RETURN: Byte length 560 * 561 * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the 562 * length of the descriptor header and the length field itself. 563 * Used to walk descriptor lists. 564 * 565 ******************************************************************************/ 566 567u32 acpi_ut_get_descriptor_length(void *aml) 568{ 569 ACPI_FUNCTION_ENTRY(); 570 571 /* 572 * Get the Resource Length (does not include header length) and add 573 * the header length (depends on if this is a small or large resource) 574 */ 575 return (acpi_ut_get_resource_length(aml) + 576 acpi_ut_get_resource_header_length(aml)); 577} 578 579/******************************************************************************* 580 * 581 * FUNCTION: acpi_ut_get_resource_end_tag 582 * 583 * PARAMETERS: obj_desc - The resource template buffer object 584 * end_tag - Where the pointer to the end_tag is returned 585 * 586 * RETURN: Status, pointer to the end tag 587 * 588 * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template 589 * Note: allows a buffer length of zero. 590 * 591 ******************************************************************************/ 592 593acpi_status 594acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, 595 u8 ** end_tag) 596{ 597 acpi_status status; 598 599 ACPI_FUNCTION_TRACE(ut_get_resource_end_tag); 600 601 /* Allow a buffer length of zero */ 602 603 if (!obj_desc->buffer.length) { 604 *end_tag = obj_desc->buffer.pointer; 605 return_ACPI_STATUS(AE_OK); 606 } 607 608 /* Validate the template and get a pointer to the end_tag */ 609 610 status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, 611 obj_desc->buffer.length, NULL, 612 (void **)end_tag); 613 614 return_ACPI_STATUS(status); 615}