brintos

brintos / linux-shallow public Read only

0
0
Text · 21.5 KiB · 8c1a686 Raw
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