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