756 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/*******************************************************************************3 *4 * Module Name: rsutils - Utilities for the resource manager5 *6 ******************************************************************************/7 8#include <acpi/acpi.h>9#include "accommon.h"10#include "acnamesp.h"11#include "acresrc.h"12 13#define _COMPONENT ACPI_RESOURCES14ACPI_MODULE_NAME("rsutils")15 16/*******************************************************************************17 *18 * FUNCTION: acpi_rs_decode_bitmask19 *20 * PARAMETERS: mask - Bitmask to decode21 * list - Where the converted list is returned22 *23 * RETURN: Count of bits set (length of list)24 *25 * DESCRIPTION: Convert a bit mask into a list of values26 *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_bitmask52 *53 * PARAMETERS: list - List of values to encode54 * count - Length of list55 *56 * RETURN: Encoded bitmask57 *58 * DESCRIPTION: Convert a list of values to an encoded bitmask59 *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_data81 *82 * PARAMETERS: destination - Pointer to the destination descriptor83 * source - Pointer to the source descriptor84 * item_count - How many items to move85 * move_type - Byte width86 *87 * RETURN: None88 *89 * DESCRIPTION: Move multiple data items from one descriptor to another. Handles90 * alignment issues and endian issues if necessary, as configured91 * via the ACPI_MOVE_* macros. (This is why a memcpy is not used)92 *93 ******************************************************************************/94 95void96acpi_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 once108 * since there are no alignment or endian issues109 */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 perform120 * endian conversion and/or accommodate hardware that cannot perform121 * misaligned memory transfers122 */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_length152 *153 * PARAMETERS: total_length - Length of the AML descriptor, including154 * the header and length fields.155 * aml - Pointer to the raw AML descriptor156 *157 * RETURN: None158 *159 * DESCRIPTION: Set the resource_length field of an AML160 * resource descriptor, both Large and Small descriptors are161 * supported automatically. Note: Descriptor Type field must162 * be valid.163 *164 ******************************************************************************/165 166void167acpi_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 length190 * Clear any existing length, preserving descriptor type bits191 */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_header202 *203 * PARAMETERS: descriptor_type - Byte to be inserted as the type204 * total_length - Length of the AML descriptor, including205 * the header and length fields.206 * aml - Pointer to the raw AML descriptor207 *208 * RETURN: None209 *210 * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML211 * resource descriptor, both Large and Small descriptors are212 * supported automatically213 *214 ******************************************************************************/215 216void217acpi_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_strcpy235 *236 * PARAMETERS: destination - Pointer to the destination string237 * source - Pointer to the source string238 *239 * RETURN: String length, including NULL terminator240 *241 * DESCRIPTION: Local string copy that returns the string length, saving a242 * 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_source266 *267 * PARAMETERS: resource_length - Length field of the descriptor268 * minimum_length - Minimum length of the descriptor (minus269 * any optional fields)270 * resource_source - Where the resource_source is returned271 * aml - Pointer to the raw AML descriptor272 * string_ptr - (optional) where to store the actual273 * resource_source string274 *275 * RETURN: Length of the string plus NULL terminator, rounded up to native276 * word boundary277 *278 * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor279 * to an internal resource descriptor280 *281 ******************************************************************************/282 283acpi_rs_length284acpi_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 longer300 * than the minimum length.301 *302 * Note: Some resource descriptors will have an additional null, so303 * 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 String315 * 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 native324 * 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_source358 *359 * PARAMETERS: aml - Pointer to the raw AML descriptor360 * minimum_length - Minimum length of the descriptor (minus361 * any optional fields)362 * resource_source - Internal resource_source363 364 *365 * RETURN: Total length of the AML descriptor366 *367 * DESCRIPTION: Convert an optional resource_source from internal format to a368 * raw AML resource descriptor369 *370 ******************************************************************************/371 372acpi_rsdesc_size373acpi_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 the403 * final descriptor length404 */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_data417 *418 * PARAMETERS: node - Device node419 * ret_buffer - Pointer to a buffer structure for the420 * results421 *422 * RETURN: Status423 *424 * DESCRIPTION: This function is called to get the _PRT value of an object425 * contained in an object specified by the handle passed in426 *427 * If the function fails an appropriate status will be returned428 * and the contents of the callers buffer is undefined.429 *430 ******************************************************************************/431 432acpi_status433acpi_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 comes454 * 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_data467 *468 * PARAMETERS: node - Device node469 * ret_buffer - Pointer to a buffer structure for the470 * results471 *472 * RETURN: Status473 *474 * DESCRIPTION: This function is called to get the _CRS value of an object475 * contained in an object specified by the handle passed in476 *477 * If the function fails an appropriate status will be returned478 * and the contents of the callers buffer is undefined.479 *480 ******************************************************************************/481 482acpi_status483acpi_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 the504 * byte stream buffer that comes back from the _CRS method505 * 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_data518 *519 * PARAMETERS: node - Device node520 * ret_buffer - Pointer to a buffer structure for the521 * results522 *523 * RETURN: Status524 *525 * DESCRIPTION: This function is called to get the _PRS value of an object526 * contained in an object specified by the handle passed in527 *528 * If the function fails an appropriate status will be returned529 * and the contents of the callers buffer is undefined.530 *531 ******************************************************************************/532 533acpi_status534acpi_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 the555 * byte stream buffer that comes back from the _CRS method556 * 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_data569 *570 * PARAMETERS: node - Device node571 * ret_buffer - Pointer to a buffer structure for the572 * results573 *574 * RETURN: Status575 *576 * DESCRIPTION: This function is called to get the _AEI value of an object577 * contained in an object specified by the handle passed in578 *579 * If the function fails an appropriate status will be returned580 * and the contents of the callers buffer is undefined.581 *582 ******************************************************************************/583 584acpi_status585acpi_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 the606 * byte stream buffer that comes back from the _CRS method607 * 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_data620 *621 * PARAMETERS: handle - Handle to the containing object622 * path - Path to method, relative to Handle623 * ret_buffer - Pointer to a buffer structure for the624 * results625 *626 * RETURN: Status627 *628 * DESCRIPTION: This function is called to get the _CRS or _PRS value of an629 * object contained in an object specified by the handle passed in630 *631 * If the function fails an appropriate status will be returned632 * and the contents of the callers buffer is undefined.633 *634 ******************************************************************************/635 636acpi_status637acpi_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_PTR651 (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 the659 * byte stream buffer that comes back from the method660 * 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_data673 *674 * PARAMETERS: node - Device node675 * in_buffer - Pointer to a buffer structure of the676 * parameter677 *678 * RETURN: Status679 *680 * DESCRIPTION: This function is called to set the _SRS of an object contained681 * in an object specified by the handle passed in682 *683 * If the function fails an appropriate status will be returned684 * and the contents of the callers buffer is undefined.685 *686 * Note: Parameters guaranteed valid by caller687 *688 ******************************************************************************/689 690acpi_status691acpi_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 of715 * resource parameters. It needs to be formatted into a716 * byte stream to be sent in as an input parameter to _SRS717 *718 * Convert the linked list into a byte stream719 */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 freed732 * 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}756