1/******************************************************************************* 2 * 3 * Module Name: rsutils - Utilities for the resource manager 4 * 5 ******************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2007, R. Byron Moore 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/acnamesp.h> 46#include <acpi/acresrc.h> 47 48#define _COMPONENT ACPI_RESOURCES 49ACPI_MODULE_NAME("rsutils") 50 51/******************************************************************************* 52 * 53 * FUNCTION: acpi_rs_decode_bitmask 54 * 55 * PARAMETERS: Mask - Bitmask to decode 56 * List - Where the converted list is returned 57 * 58 * RETURN: Count of bits set (length of list) 59 * 60 * DESCRIPTION: Convert a bit mask into a list of values 61 * 62 ******************************************************************************/ 63u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) 64{ 65 acpi_native_uint i; 66 u8 bit_count; 67 68 ACPI_FUNCTION_ENTRY(); 69 70 /* Decode the mask bits */ 71 72 for (i = 0, bit_count = 0; mask; i++) { 73 if (mask & 0x0001) { 74 list[bit_count] = (u8) i; 75 bit_count++; 76 } 77 78 mask >>= 1; 79 } 80 81 return (bit_count); 82} 83 84/******************************************************************************* 85 * 86 * FUNCTION: acpi_rs_encode_bitmask 87 * 88 * PARAMETERS: List - List of values to encode 89 * Count - Length of list 90 * 91 * RETURN: Encoded bitmask 92 * 93 * DESCRIPTION: Convert a list of values to an encoded bitmask 94 * 95 ******************************************************************************/ 96 97u16 acpi_rs_encode_bitmask(u8 * list, u8 count) 98{ 99 acpi_native_uint i; 100 u16 mask; 101 102 ACPI_FUNCTION_ENTRY(); 103 104 /* Encode the list into a single bitmask */ 105 106 for (i = 0, mask = 0; i < count; i++) { 107 mask |= (0x0001 << list[i]); 108 } 109 110 return (mask); 111} 112 113/******************************************************************************* 114 * 115 * FUNCTION: acpi_rs_move_data 116 * 117 * PARAMETERS: Destination - Pointer to the destination descriptor 118 * Source - Pointer to the source descriptor 119 * item_count - How many items to move 120 * move_type - Byte width 121 * 122 * RETURN: None 123 * 124 * DESCRIPTION: Move multiple data items from one descriptor to another. Handles 125 * alignment issues and endian issues if necessary, as configured 126 * via the ACPI_MOVE_* macros. (This is why a memcpy is not used) 127 * 128 ******************************************************************************/ 129 130void 131acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) 132{ 133 acpi_native_uint i; 134 135 ACPI_FUNCTION_ENTRY(); 136 137 /* One move per item */ 138 139 for (i = 0; i < item_count; i++) { 140 switch (move_type) { 141 /* 142 * For the 8-bit case, we can perform the move all at once 143 * since there are no alignment or endian issues 144 */ 145 case ACPI_RSC_MOVE8: 146 ACPI_MEMCPY(destination, source, item_count); 147 return; 148 149 /* 150 * 16-, 32-, and 64-bit cases must use the move macros that perform 151 * endian conversion and/or accomodate hardware that cannot perform 152 * misaligned memory transfers 153 */ 154 case ACPI_RSC_MOVE16: 155 ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i], 156 &ACPI_CAST_PTR(u16, source)[i]); 157 break; 158 159 case ACPI_RSC_MOVE32: 160 ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i], 161 &ACPI_CAST_PTR(u32, source)[i]); 162 break; 163 164 case ACPI_RSC_MOVE64: 165 ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i], 166 &ACPI_CAST_PTR(u64, source)[i]); 167 break; 168 169 default: 170 return; 171 } 172 } 173} 174 175/******************************************************************************* 176 * 177 * FUNCTION: acpi_rs_set_resource_length 178 * 179 * PARAMETERS: total_length - Length of the AML descriptor, including 180 * the header and length fields. 181 * Aml - Pointer to the raw AML descriptor 182 * 183 * RETURN: None 184 * 185 * DESCRIPTION: Set the resource_length field of an AML 186 * resource descriptor, both Large and Small descriptors are 187 * supported automatically. Note: Descriptor Type field must 188 * be valid. 189 * 190 ******************************************************************************/ 191 192void 193acpi_rs_set_resource_length(acpi_rsdesc_size total_length, 194 union aml_resource *aml) 195{ 196 acpi_rs_length resource_length; 197 198 ACPI_FUNCTION_ENTRY(); 199 200 /* Length is the total descriptor length minus the header length */ 201 202 resource_length = (acpi_rs_length) 203 (total_length - acpi_ut_get_resource_header_length(aml)); 204 205 /* Length is stored differently for large and small descriptors */ 206 207 if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) { 208 209 /* Large descriptor -- bytes 1-2 contain the 16-bit length */ 210 211 ACPI_MOVE_16_TO_16(&aml->large_header.resource_length, 212 &resource_length); 213 } else { 214 /* Small descriptor -- bits 2:0 of byte 0 contain the length */ 215 216 aml->small_header.descriptor_type = (u8) 217 218 /* Clear any existing length, preserving descriptor type bits */ 219 ((aml->small_header. 220 descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK) 221 222 | resource_length); 223 } 224} 225 226/******************************************************************************* 227 * 228 * FUNCTION: acpi_rs_set_resource_header 229 * 230 * PARAMETERS: descriptor_type - Byte to be inserted as the type 231 * total_length - Length of the AML descriptor, including 232 * the header and length fields. 233 * Aml - Pointer to the raw AML descriptor 234 * 235 * RETURN: None 236 * 237 * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML 238 * resource descriptor, both Large and Small descriptors are 239 * supported automatically 240 * 241 ******************************************************************************/ 242 243void 244acpi_rs_set_resource_header(u8 descriptor_type, 245 acpi_rsdesc_size total_length, 246 union aml_resource *aml) 247{ 248 ACPI_FUNCTION_ENTRY(); 249 250 /* Set the Resource Type */ 251 252 aml->small_header.descriptor_type = descriptor_type; 253 254 /* Set the Resource Length */ 255 256 acpi_rs_set_resource_length(total_length, aml); 257} 258 259/******************************************************************************* 260 * 261 * FUNCTION: acpi_rs_strcpy 262 * 263 * PARAMETERS: Destination - Pointer to the destination string 264 * Source - Pointer to the source string 265 * 266 * RETURN: String length, including NULL terminator 267 * 268 * DESCRIPTION: Local string copy that returns the string length, saving a 269 * strcpy followed by a strlen. 270 * 271 ******************************************************************************/ 272 273static u16 acpi_rs_strcpy(char *destination, char *source) 274{ 275 u16 i; 276 277 ACPI_FUNCTION_ENTRY(); 278 279 for (i = 0; source[i]; i++) { 280 destination[i] = source[i]; 281 } 282 283 destination[i] = 0; 284 285 /* Return string length including the NULL terminator */ 286 287 return ((u16) (i + 1)); 288} 289 290/******************************************************************************* 291 * 292 * FUNCTION: acpi_rs_get_resource_source 293 * 294 * PARAMETERS: resource_length - Length field of the descriptor 295 * minimum_length - Minimum length of the descriptor (minus 296 * any optional fields) 297 * resource_source - Where the resource_source is returned 298 * Aml - Pointer to the raw AML descriptor 299 * string_ptr - (optional) where to store the actual 300 * resource_source string 301 * 302 * RETURN: Length of the string plus NULL terminator, rounded up to native 303 * word boundary 304 * 305 * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor 306 * to an internal resource descriptor 307 * 308 ******************************************************************************/ 309 310acpi_rs_length 311acpi_rs_get_resource_source(acpi_rs_length resource_length, 312 acpi_rs_length minimum_length, 313 struct acpi_resource_source * resource_source, 314 union aml_resource * aml, char *string_ptr) 315{ 316 acpi_rsdesc_size total_length; 317 u8 *aml_resource_source; 318 319 ACPI_FUNCTION_ENTRY(); 320 321 total_length = 322 resource_length + sizeof(struct aml_resource_large_header); 323 aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); 324 325 /* 326 * resource_source is present if the length of the descriptor is longer than 327 * the minimum length. 328 * 329 * Note: Some resource descriptors will have an additional null, so 330 * we add 1 to the minimum length. 331 */ 332 if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) { 333 334 /* Get the resource_source_index */ 335 336 resource_source->index = aml_resource_source[0]; 337 338 resource_source->string_ptr = string_ptr; 339 if (!string_ptr) { 340 /* 341 * String destination pointer is not specified; Set the String 342 * pointer to the end of the current resource_source structure. 343 */ 344 resource_source->string_ptr = 345 ACPI_ADD_PTR(char, resource_source, 346 sizeof(struct acpi_resource_source)); 347 } 348 349 /* 350 * In order for the Resource length to be a multiple of the native 351 * word, calculate the length of the string (+1 for NULL terminator) 352 * and expand to the next word multiple. 353 * 354 * Zero the entire area of the buffer. 355 */ 356 total_length = (u32) 357 ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; 358 total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); 359 360 ACPI_MEMSET(resource_source->string_ptr, 0, total_length); 361 362 /* Copy the resource_source string to the destination */ 363 364 resource_source->string_length = 365 acpi_rs_strcpy(resource_source->string_ptr, 366 ACPI_CAST_PTR(char, 367 &aml_resource_source[1])); 368 369 return ((acpi_rs_length) total_length); 370 } 371 372 /* resource_source is not present */ 373 374 resource_source->index = 0; 375 resource_source->string_length = 0; 376 resource_source->string_ptr = NULL; 377 return (0); 378} 379 380/******************************************************************************* 381 * 382 * FUNCTION: acpi_rs_set_resource_source 383 * 384 * PARAMETERS: Aml - Pointer to the raw AML descriptor 385 * minimum_length - Minimum length of the descriptor (minus 386 * any optional fields) 387 * resource_source - Internal resource_source 388 389 * 390 * RETURN: Total length of the AML descriptor 391 * 392 * DESCRIPTION: Convert an optional resource_source from internal format to a 393 * raw AML resource descriptor 394 * 395 ******************************************************************************/ 396 397acpi_rsdesc_size 398acpi_rs_set_resource_source(union aml_resource * aml, 399 acpi_rs_length minimum_length, 400 struct acpi_resource_source * resource_source) 401{ 402 u8 *aml_resource_source; 403 acpi_rsdesc_size descriptor_length; 404 405 ACPI_FUNCTION_ENTRY(); 406 407 descriptor_length = minimum_length; 408 409 /* Non-zero string length indicates presence of a resource_source */ 410 411 if (resource_source->string_length) { 412 413 /* Point to the end of the AML descriptor */ 414 415 aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); 416 417 /* Copy the resource_source_index */ 418 419 aml_resource_source[0] = (u8) resource_source->index; 420 421 /* Copy the resource_source string */ 422 423 ACPI_STRCPY(ACPI_CAST_PTR(char, &aml_resource_source[1]), 424 resource_source->string_ptr); 425 426 /* 427 * Add the length of the string (+ 1 for null terminator) to the 428 * final descriptor length 429 */ 430 descriptor_length += 431 ((acpi_rsdesc_size) resource_source->string_length + 1); 432 } 433 434 /* Return the new total length of the AML descriptor */ 435 436 return (descriptor_length); 437} 438 439/******************************************************************************* 440 * 441 * FUNCTION: acpi_rs_get_prt_method_data 442 * 443 * PARAMETERS: Node - Device node 444 * ret_buffer - Pointer to a buffer structure for the 445 * results 446 * 447 * RETURN: Status 448 * 449 * DESCRIPTION: This function is called to get the _PRT value of an object 450 * contained in an object specified by the handle passed in 451 * 452 * If the function fails an appropriate status will be returned 453 * and the contents of the callers buffer is undefined. 454 * 455 ******************************************************************************/ 456 457acpi_status 458acpi_rs_get_prt_method_data(struct acpi_namespace_node * node, 459 struct acpi_buffer * ret_buffer) 460{ 461 union acpi_operand_object *obj_desc; 462 acpi_status status; 463 464 ACPI_FUNCTION_TRACE(rs_get_prt_method_data); 465 466 /* Parameters guaranteed valid by caller */ 467 468 /* Execute the method, no parameters */ 469 470 status = acpi_ut_evaluate_object(node, METHOD_NAME__PRT, 471 ACPI_BTYPE_PACKAGE, &obj_desc); 472 if (ACPI_FAILURE(status)) { 473 return_ACPI_STATUS(status); 474 } 475 476 /* 477 * Create a resource linked list from the byte stream buffer that comes 478 * back from the _CRS method execution. 479 */ 480 status = acpi_rs_create_pci_routing_table(obj_desc, ret_buffer); 481 482 /* On exit, we must delete the object returned by evaluate_object */ 483 484 acpi_ut_remove_reference(obj_desc); 485 return_ACPI_STATUS(status); 486} 487 488/******************************************************************************* 489 * 490 * FUNCTION: acpi_rs_get_crs_method_data 491 * 492 * PARAMETERS: Node - Device node 493 * ret_buffer - Pointer to a buffer structure for the 494 * results 495 * 496 * RETURN: Status 497 * 498 * DESCRIPTION: This function is called to get the _CRS value of an object 499 * contained in an object specified by the handle passed in 500 * 501 * If the function fails an appropriate status will be returned 502 * and the contents of the callers buffer is undefined. 503 * 504 ******************************************************************************/ 505 506acpi_status 507acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, 508 struct acpi_buffer *ret_buffer) 509{ 510 union acpi_operand_object *obj_desc; 511 acpi_status status; 512 513 ACPI_FUNCTION_TRACE(rs_get_crs_method_data); 514 515 /* Parameters guaranteed valid by caller */ 516 517 /* Execute the method, no parameters */ 518 519 status = acpi_ut_evaluate_object(node, METHOD_NAME__CRS, 520 ACPI_BTYPE_BUFFER, &obj_desc); 521 if (ACPI_FAILURE(status)) { 522 return_ACPI_STATUS(status); 523 } 524 525 /* 526 * Make the call to create a resource linked list from the 527 * byte stream buffer that comes back from the _CRS method 528 * execution. 529 */ 530 status = acpi_rs_create_resource_list(obj_desc, ret_buffer); 531 532 /* On exit, we must delete the object returned by evaluate_object */ 533 534 acpi_ut_remove_reference(obj_desc); 535 return_ACPI_STATUS(status); 536} 537 538/******************************************************************************* 539 * 540 * FUNCTION: acpi_rs_get_prs_method_data 541 * 542 * PARAMETERS: Node - Device node 543 * ret_buffer - Pointer to a buffer structure for the 544 * results 545 * 546 * RETURN: Status 547 * 548 * DESCRIPTION: This function is called to get the _PRS value of an object 549 * contained in an object specified by the handle passed in 550 * 551 * If the function fails an appropriate status will be returned 552 * and the contents of the callers buffer is undefined. 553 * 554 ******************************************************************************/ 555 556#ifdef ACPI_FUTURE_USAGE 557acpi_status 558acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, 559 struct acpi_buffer *ret_buffer) 560{ 561 union acpi_operand_object *obj_desc; 562 acpi_status status; 563 564 ACPI_FUNCTION_TRACE(rs_get_prs_method_data); 565 566 /* Parameters guaranteed valid by caller */ 567 568 /* Execute the method, no parameters */ 569 570 status = acpi_ut_evaluate_object(node, METHOD_NAME__PRS, 571 ACPI_BTYPE_BUFFER, &obj_desc); 572 if (ACPI_FAILURE(status)) { 573 return_ACPI_STATUS(status); 574 } 575 576 /* 577 * Make the call to create a resource linked list from the 578 * byte stream buffer that comes back from the _CRS method 579 * execution. 580 */ 581 status = acpi_rs_create_resource_list(obj_desc, ret_buffer); 582 583 /* On exit, we must delete the object returned by evaluate_object */ 584 585 acpi_ut_remove_reference(obj_desc); 586 return_ACPI_STATUS(status); 587} 588#endif /* ACPI_FUTURE_USAGE */ 589 590/******************************************************************************* 591 * 592 * FUNCTION: acpi_rs_get_method_data 593 * 594 * PARAMETERS: Handle - Handle to the containing object 595 * Path - Path to method, relative to Handle 596 * ret_buffer - Pointer to a buffer structure for the 597 * results 598 * 599 * RETURN: Status 600 * 601 * DESCRIPTION: This function is called to get the _CRS or _PRS value of an 602 * object contained in an object specified by the handle passed in 603 * 604 * If the function fails an appropriate status will be returned 605 * and the contents of the callers buffer is undefined. 606 * 607 ******************************************************************************/ 608 609acpi_status 610acpi_rs_get_method_data(acpi_handle handle, 611 char *path, struct acpi_buffer *ret_buffer) 612{ 613 union acpi_operand_object *obj_desc; 614 acpi_status status; 615 616 ACPI_FUNCTION_TRACE(rs_get_method_data); 617 618 /* Parameters guaranteed valid by caller */ 619 620 /* Execute the method, no parameters */ 621 622 status = 623 acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc); 624 if (ACPI_FAILURE(status)) { 625 return_ACPI_STATUS(status); 626 } 627 628 /* 629 * Make the call to create a resource linked list from the 630 * byte stream buffer that comes back from the method 631 * execution. 632 */ 633 status = acpi_rs_create_resource_list(obj_desc, ret_buffer); 634 635 /* On exit, we must delete the object returned by evaluate_object */ 636 637 acpi_ut_remove_reference(obj_desc); 638 return_ACPI_STATUS(status); 639} 640 641/******************************************************************************* 642 * 643 * FUNCTION: acpi_rs_set_srs_method_data 644 * 645 * PARAMETERS: Node - Device node 646 * in_buffer - Pointer to a buffer structure of the 647 * parameter 648 * 649 * RETURN: Status 650 * 651 * DESCRIPTION: This function is called to set the _SRS of an object contained 652 * in an object specified by the handle passed in 653 * 654 * If the function fails an appropriate status will be returned 655 * and the contents of the callers buffer is undefined. 656 * 657 * Note: Parameters guaranteed valid by caller 658 * 659 ******************************************************************************/ 660 661acpi_status 662acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, 663 struct acpi_buffer *in_buffer) 664{ 665 struct acpi_evaluate_info *info; 666 union acpi_operand_object *args[2]; 667 acpi_status status; 668 struct acpi_buffer buffer; 669 670 ACPI_FUNCTION_TRACE(rs_set_srs_method_data); 671 672 /* Allocate and initialize the evaluation information block */ 673 674 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); 675 if (!info) { 676 return_ACPI_STATUS(AE_NO_MEMORY); 677 } 678 679 info->prefix_node = node; 680 info->pathname = METHOD_NAME__SRS; 681 info->parameters = args; 682 info->parameter_type = ACPI_PARAM_ARGS; 683 info->flags = ACPI_IGNORE_RETURN_VALUE; 684 685 /* 686 * The in_buffer parameter will point to a linked list of 687 * resource parameters. It needs to be formatted into a 688 * byte stream to be sent in as an input parameter to _SRS 689 * 690 * Convert the linked list into a byte stream 691 */ 692 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 693 status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer); 694 if (ACPI_FAILURE(status)) { 695 goto cleanup; 696 } 697 698 /* Create and initialize the method parameter object */ 699 700 args[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); 701 if (!args[0]) { 702 /* 703 * Must free the buffer allocated above (otherwise it is freed 704 * later) 705 */ 706 ACPI_FREE(buffer.pointer); 707 status = AE_NO_MEMORY; 708 goto cleanup; 709 } 710 711 args[0]->buffer.length = (u32) buffer.length; 712 args[0]->buffer.pointer = buffer.pointer; 713 args[0]->common.flags = AOPOBJ_DATA_VALID; 714 args[1] = NULL; 715 716 /* Execute the method, no return value is expected */ 717 718 status = acpi_ns_evaluate(info); 719 720 /* Clean up and return the status from acpi_ns_evaluate */ 721 722 acpi_ut_remove_reference(args[0]); 723 724 cleanup: 725 ACPI_FREE(info); 726 return_ACPI_STATUS(status); 727} 728