brintos

brintos / linux-shallow public Read only

0
0
Text · 12.9 KiB · 7e5a683 Raw
491 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: nsconvert - Object conversions for objects returned by5 *                          predefined methods6 *7 * Copyright (C) 2000 - 2023, Intel Corp.8 *9 *****************************************************************************/10 11#include <acpi/acpi.h>12#include "accommon.h"13#include "acnamesp.h"14#include "acinterp.h"15#include "acpredef.h"16#include "amlresrc.h"17 18#define _COMPONENT          ACPI_NAMESPACE19ACPI_MODULE_NAME("nsconvert")20 21/*******************************************************************************22 *23 * FUNCTION:    acpi_ns_convert_to_integer24 *25 * PARAMETERS:  original_object     - Object to be converted26 *              return_object       - Where the new converted object is returned27 *28 * RETURN:      Status. AE_OK if conversion was successful.29 *30 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.31 *32 ******************************************************************************/33acpi_status34acpi_ns_convert_to_integer(union acpi_operand_object *original_object,35			   union acpi_operand_object **return_object)36{37	union acpi_operand_object *new_object;38	acpi_status status;39	u64 value = 0;40	u32 i;41 42	switch (original_object->common.type) {43	case ACPI_TYPE_STRING:44 45		/* String-to-Integer conversion */46 47		status =48		    acpi_ut_strtoul64(original_object->string.pointer, &value);49		if (ACPI_FAILURE(status)) {50			return (status);51		}52		break;53 54	case ACPI_TYPE_BUFFER:55 56		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */57 58		if (original_object->buffer.length > 8) {59			return (AE_AML_OPERAND_TYPE);60		}61 62		/* Extract each buffer byte to create the integer */63 64		for (i = 0; i < original_object->buffer.length; i++) {65			value |= ((u64)66				  original_object->buffer.pointer[i] << (i *67									 8));68		}69		break;70 71	default:72 73		return (AE_AML_OPERAND_TYPE);74	}75 76	new_object = acpi_ut_create_integer_object(value);77	if (!new_object) {78		return (AE_NO_MEMORY);79	}80 81	*return_object = new_object;82	return (AE_OK);83}84 85/*******************************************************************************86 *87 * FUNCTION:    acpi_ns_convert_to_string88 *89 * PARAMETERS:  original_object     - Object to be converted90 *              return_object       - Where the new converted object is returned91 *92 * RETURN:      Status. AE_OK if conversion was successful.93 *94 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.95 *96 ******************************************************************************/97 98acpi_status99acpi_ns_convert_to_string(union acpi_operand_object *original_object,100			  union acpi_operand_object **return_object)101{102	union acpi_operand_object *new_object;103	acpi_size length;104	acpi_status status;105 106	switch (original_object->common.type) {107	case ACPI_TYPE_INTEGER:108		/*109		 * Integer-to-String conversion. Commonly, convert110		 * an integer of value 0 to a NULL string. The last element of111		 * _BIF and _BIX packages occasionally need this fix.112		 */113		if (original_object->integer.value == 0) {114 115			/* Allocate a new NULL string object */116 117			new_object = acpi_ut_create_string_object(0);118			if (!new_object) {119				return (AE_NO_MEMORY);120			}121		} else {122			status = acpi_ex_convert_to_string(original_object,123							   &new_object,124							   ACPI_IMPLICIT_CONVERT_HEX);125			if (ACPI_FAILURE(status)) {126				return (status);127			}128		}129		break;130 131	case ACPI_TYPE_BUFFER:132		/*133		 * Buffer-to-String conversion. Use a to_string134		 * conversion, no transform performed on the buffer data. The best135		 * example of this is the _BIF method, where the string data from136		 * the battery is often (incorrectly) returned as buffer object(s).137		 */138		length = 0;139		while ((length < original_object->buffer.length) &&140		       (original_object->buffer.pointer[length])) {141			length++;142		}143 144		/* Allocate a new string object */145 146		new_object = acpi_ut_create_string_object(length);147		if (!new_object) {148			return (AE_NO_MEMORY);149		}150 151		/*152		 * Copy the raw buffer data with no transform. String is already NULL153		 * terminated at Length+1.154		 */155		memcpy(new_object->string.pointer,156		       original_object->buffer.pointer, length);157		break;158 159	default:160 161		return (AE_AML_OPERAND_TYPE);162	}163 164	*return_object = new_object;165	return (AE_OK);166}167 168/*******************************************************************************169 *170 * FUNCTION:    acpi_ns_convert_to_buffer171 *172 * PARAMETERS:  original_object     - Object to be converted173 *              return_object       - Where the new converted object is returned174 *175 * RETURN:      Status. AE_OK if conversion was successful.176 *177 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.178 *179 ******************************************************************************/180 181acpi_status182acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,183			  union acpi_operand_object **return_object)184{185	union acpi_operand_object *new_object;186	acpi_status status;187	union acpi_operand_object **elements;188	u32 *dword_buffer;189	u32 count;190	u32 i;191 192	switch (original_object->common.type) {193	case ACPI_TYPE_INTEGER:194		/*195		 * Integer-to-Buffer conversion.196		 * Convert the Integer to a packed-byte buffer. _MAT and other197		 * objects need this sometimes, if a read has been performed on a198		 * Field object that is less than or equal to the global integer199		 * size (32 or 64 bits).200		 */201		status =202		    acpi_ex_convert_to_buffer(original_object, &new_object);203		if (ACPI_FAILURE(status)) {204			return (status);205		}206		break;207 208	case ACPI_TYPE_STRING:209 210		/* String-to-Buffer conversion. Simple data copy */211 212		new_object = acpi_ut_create_buffer_object213		    (original_object->string.length);214		if (!new_object) {215			return (AE_NO_MEMORY);216		}217 218		memcpy(new_object->buffer.pointer,219		       original_object->string.pointer,220		       original_object->string.length);221		break;222 223	case ACPI_TYPE_PACKAGE:224		/*225		 * This case is often seen for predefined names that must return a226		 * Buffer object with multiple DWORD integers within. For example,227		 * _FDE and _GTM. The Package can be converted to a Buffer.228		 */229 230		/* All elements of the Package must be integers */231 232		elements = original_object->package.elements;233		count = original_object->package.count;234 235		for (i = 0; i < count; i++) {236			if ((!*elements) ||237			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {238				return (AE_AML_OPERAND_TYPE);239			}240			elements++;241		}242 243		/* Create the new buffer object to replace the Package */244 245		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));246		if (!new_object) {247			return (AE_NO_MEMORY);248		}249 250		/* Copy the package elements (integers) to the buffer as DWORDs */251 252		elements = original_object->package.elements;253		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);254 255		for (i = 0; i < count; i++) {256			*dword_buffer = (u32)(*elements)->integer.value;257			dword_buffer++;258			elements++;259		}260		break;261 262	default:263 264		return (AE_AML_OPERAND_TYPE);265	}266 267	*return_object = new_object;268	return (AE_OK);269}270 271/*******************************************************************************272 *273 * FUNCTION:    acpi_ns_convert_to_unicode274 *275 * PARAMETERS:  scope               - Namespace node for the method/object276 *              original_object     - ASCII String Object to be converted277 *              return_object       - Where the new converted object is returned278 *279 * RETURN:      Status. AE_OK if conversion was successful.280 *281 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.282 *283 ******************************************************************************/284 285acpi_status286acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope,287			   union acpi_operand_object *original_object,288			   union acpi_operand_object **return_object)289{290	union acpi_operand_object *new_object;291	char *ascii_string;292	u16 *unicode_buffer;293	u32 unicode_length;294	u32 i;295 296	if (!original_object) {297		return (AE_OK);298	}299 300	/* If a Buffer was returned, it must be at least two bytes long */301 302	if (original_object->common.type == ACPI_TYPE_BUFFER) {303		if (original_object->buffer.length < 2) {304			return (AE_AML_OPERAND_VALUE);305		}306 307		*return_object = NULL;308		return (AE_OK);309	}310 311	/*312	 * The original object is an ASCII string. Convert this string to313	 * a unicode buffer.314	 */315	ascii_string = original_object->string.pointer;316	unicode_length = (original_object->string.length * 2) + 2;317 318	/* Create a new buffer object for the Unicode data */319 320	new_object = acpi_ut_create_buffer_object(unicode_length);321	if (!new_object) {322		return (AE_NO_MEMORY);323	}324 325	unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);326 327	/* Convert ASCII to Unicode */328 329	for (i = 0; i < original_object->string.length; i++) {330		unicode_buffer[i] = (u16)ascii_string[i];331	}332 333	*return_object = new_object;334	return (AE_OK);335}336 337/*******************************************************************************338 *339 * FUNCTION:    acpi_ns_convert_to_resource340 *341 * PARAMETERS:  scope               - Namespace node for the method/object342 *              original_object     - Object to be converted343 *              return_object       - Where the new converted object is returned344 *345 * RETURN:      Status. AE_OK if conversion was successful346 *347 * DESCRIPTION: Attempt to convert a Integer object to a resource_template348 *              Buffer.349 *350 ******************************************************************************/351 352acpi_status353acpi_ns_convert_to_resource(struct acpi_namespace_node *scope,354			    union acpi_operand_object *original_object,355			    union acpi_operand_object **return_object)356{357	union acpi_operand_object *new_object;358	u8 *buffer;359 360	/*361	 * We can fix the following cases for an expected resource template:362	 * 1. No return value (interpreter slack mode is disabled)363	 * 2. A "Return (Zero)" statement364	 * 3. A "Return empty buffer" statement365	 *366	 * We will return a buffer containing a single end_tag367	 * resource descriptor.368	 */369	if (original_object) {370		switch (original_object->common.type) {371		case ACPI_TYPE_INTEGER:372 373			/* We can only repair an Integer==0 */374 375			if (original_object->integer.value) {376				return (AE_AML_OPERAND_TYPE);377			}378			break;379 380		case ACPI_TYPE_BUFFER:381 382			if (original_object->buffer.length) {383 384				/* Additional checks can be added in the future */385 386				*return_object = NULL;387				return (AE_OK);388			}389			break;390 391		case ACPI_TYPE_STRING:392		default:393 394			return (AE_AML_OPERAND_TYPE);395		}396	}397 398	/* Create the new buffer object for the resource descriptor */399 400	new_object = acpi_ut_create_buffer_object(2);401	if (!new_object) {402		return (AE_NO_MEMORY);403	}404 405	buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);406 407	/* Initialize the Buffer with a single end_tag descriptor */408 409	buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);410	buffer[1] = 0x00;411 412	*return_object = new_object;413	return (AE_OK);414}415 416/*******************************************************************************417 *418 * FUNCTION:    acpi_ns_convert_to_reference419 *420 * PARAMETERS:  scope               - Namespace node for the method/object421 *              original_object     - Object to be converted422 *              return_object       - Where the new converted object is returned423 *424 * RETURN:      Status. AE_OK if conversion was successful425 *426 * DESCRIPTION: Attempt to convert a Integer object to a object_reference.427 *              Buffer.428 *429 ******************************************************************************/430 431acpi_status432acpi_ns_convert_to_reference(struct acpi_namespace_node *scope,433			     union acpi_operand_object *original_object,434			     union acpi_operand_object **return_object)435{436	union acpi_operand_object *new_object = NULL;437	acpi_status status;438	struct acpi_namespace_node *node;439	union acpi_generic_state scope_info;440	char *name;441 442	ACPI_FUNCTION_NAME(ns_convert_to_reference);443 444	/* Convert path into internal presentation */445 446	status =447	    acpi_ns_internalize_name(original_object->string.pointer, &name);448	if (ACPI_FAILURE(status)) {449		return_ACPI_STATUS(status);450	}451 452	/* Find the namespace node */453 454	scope_info.scope.node =455	    ACPI_CAST_PTR(struct acpi_namespace_node, scope);456	status =457	    acpi_ns_lookup(&scope_info, name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,458			   ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,459			   NULL, &node);460	if (ACPI_FAILURE(status)) {461 462		/* Check if we are resolving a named reference within a package */463 464		ACPI_ERROR_NAMESPACE(&scope_info,465				     original_object->string.pointer, status);466		goto error_exit;467	}468 469	/* Create and init a new internal ACPI object */470 471	new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);472	if (!new_object) {473		status = AE_NO_MEMORY;474		goto error_exit;475	}476	new_object->reference.node = node;477	new_object->reference.object = node->object;478	new_object->reference.class = ACPI_REFCLASS_NAME;479 480	/*481	 * Increase reference of the object if needed (the object is likely a482	 * null for device nodes).483	 */484	acpi_ut_add_reference(node->object);485 486error_exit:487	ACPI_FREE(name);488	*return_object = new_object;489	return (status);490}491