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