1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: nsconvert - Object conversions for objects returned by 5 * predefined methods 6 * 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_NAMESPACE 19 ACPI_MODULE_NAME("nsconvert") 20 21 /******************************************************************************* 22 * 23 * FUNCTION: acpi_ns_convert_to_integer 24 * 25 * PARAMETERS: original_object - Object to be converted 26 * return_object - Where the new converted object is returned 27 * 28 * RETURN: Status. AE_OK if conversion was successful. 29 * 30 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. 31 * 32 ******************************************************************************/ 33 acpi_status 34 acpi_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_string 88 * 89 * PARAMETERS: original_object - Object to be converted 90 * return_object - Where the new converted object is returned 91 * 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 98 acpi_status 99 acpi_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, convert 110 * an integer of value 0 to a NULL string. The last element of 111 * _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_string 134 * conversion, no transform performed on the buffer data. The best 135 * example of this is the _BIF method, where the string data from 136 * 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 NULL 153 * 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_buffer 171 * 172 * PARAMETERS: original_object - Object to be converted 173 * return_object - Where the new converted object is returned 174 * 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 181 acpi_status 182 acpi_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 other 197 * objects need this sometimes, if a read has been performed on a 198 * Field object that is less than or equal to the global integer 199 * 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_object 213 (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 a 226 * 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_unicode 274 * 275 * PARAMETERS: scope - Namespace node for the method/object 276 * original_object - ASCII String Object to be converted 277 * return_object - Where the new converted object is returned 278 * 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 285 acpi_status 286 acpi_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 to 313 * 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_resource 340 * 341 * PARAMETERS: scope - Namespace node for the method/object 342 * original_object - Object to be converted 343 * return_object - Where the new converted object is returned 344 * 345 * RETURN: Status. AE_OK if conversion was successful 346 * 347 * DESCRIPTION: Attempt to convert a Integer object to a resource_template 348 * Buffer. 349 * 350 ******************************************************************************/ 351 352 acpi_status 353 acpi_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)" statement 364 * 3. A "Return empty buffer" statement 365 * 366 * We will return a buffer containing a single end_tag 367 * 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_reference 419 * 420 * PARAMETERS: scope - Namespace node for the method/object 421 * original_object - Object to be converted 422 * return_object - Where the new converted object is returned 423 * 424 * RETURN: Status. AE_OK if conversion was successful 425 * 426 * DESCRIPTION: Attempt to convert a Integer object to a object_reference. 427 * Buffer. 428 * 429 ******************************************************************************/ 430 431 acpi_status 432 acpi_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 a 482 * null for device nodes). 483 */ 484 acpi_ut_add_reference(node->object); 485 486 error_exit: 487 ACPI_FREE(name); 488 *return_object = new_object; 489 return (status); 490 } 491