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