Branch data Line data Source code
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 - 2020, 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 : 0 : acpi_ns_convert_to_integer(union acpi_operand_object *original_object, 35 : : union acpi_operand_object **return_object) 36 : : { 37 : 0 : union acpi_operand_object *new_object; 38 : 0 : acpi_status status; 39 : 0 : u64 value = 0; 40 : 0 : u32 i; 41 : : 42 [ # # # ]: 0 : switch (original_object->common.type) { 43 : 0 : case ACPI_TYPE_STRING: 44 : : 45 : : /* String-to-Integer conversion */ 46 : : 47 : 0 : status = 48 : 0 : acpi_ut_strtoul64(original_object->string.pointer, &value); 49 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 50 : : return (status); 51 : : } 52 : : break; 53 : : 54 : 0 : case ACPI_TYPE_BUFFER: 55 : : 56 : : /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ 57 : : 58 [ # # ]: 0 : 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 [ # # ]: 0 : for (i = 0; i < original_object->buffer.length; i++) { 65 : 0 : value |= ((u64) 66 : 0 : original_object->buffer.pointer[i] << (i * 67 : : 8)); 68 : : } 69 : : break; 70 : : 71 : : default: 72 : : 73 : : return (AE_AML_OPERAND_TYPE); 74 : : } 75 : : 76 : 0 : new_object = acpi_ut_create_integer_object(value); 77 [ # # ]: 0 : if (!new_object) { 78 : : return (AE_NO_MEMORY); 79 : : } 80 : : 81 : 0 : *return_object = new_object; 82 : 0 : 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 : 0 : acpi_ns_convert_to_string(union acpi_operand_object *original_object, 100 : : union acpi_operand_object **return_object) 101 : : { 102 : 0 : union acpi_operand_object *new_object; 103 : 0 : acpi_size length; 104 : 0 : acpi_status status; 105 : : 106 [ # # # ]: 0 : switch (original_object->common.type) { 107 : 0 : 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 [ # # ]: 0 : if (original_object->integer.value == 0) { 114 : : 115 : : /* Allocate a new NULL string object */ 116 : : 117 : 0 : new_object = acpi_ut_create_string_object(0); 118 [ # # ]: 0 : if (!new_object) { 119 : : return (AE_NO_MEMORY); 120 : : } 121 : : } else { 122 : 0 : status = acpi_ex_convert_to_string(original_object, 123 : : &new_object, 124 : : ACPI_IMPLICIT_CONVERT_HEX); 125 [ # # ]: 0 : 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 [ # # ]: 0 : while ((length < original_object->buffer.length) && 140 [ # # ]: 0 : (original_object->buffer.pointer[length])) { 141 : 0 : length++; 142 : : } 143 : : 144 : : /* Allocate a new string object */ 145 : : 146 : 0 : new_object = acpi_ut_create_string_object(length); 147 [ # # ]: 0 : 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 : 0 : memcpy(new_object->string.pointer, 156 : 0 : original_object->buffer.pointer, length); 157 : 0 : break; 158 : : 159 : : default: 160 : : 161 : : return (AE_AML_OPERAND_TYPE); 162 : : } 163 : : 164 : 0 : *return_object = new_object; 165 : 0 : 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 : 0 : acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 183 : : union acpi_operand_object **return_object) 184 : : { 185 : 0 : union acpi_operand_object *new_object; 186 : 0 : acpi_status status; 187 : 0 : union acpi_operand_object **elements; 188 : 0 : u32 *dword_buffer; 189 : 0 : u32 count; 190 : 0 : u32 i; 191 : : 192 [ # # # # ]: 0 : switch (original_object->common.type) { 193 : 0 : 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 : 0 : status = 202 : 0 : acpi_ex_convert_to_buffer(original_object, &new_object); 203 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 204 : : return (status); 205 : : } 206 : : break; 207 : : 208 : 0 : case ACPI_TYPE_STRING: 209 : : 210 : : /* String-to-Buffer conversion. Simple data copy */ 211 : : 212 : 0 : new_object = acpi_ut_create_buffer_object 213 : 0 : (original_object->string.length); 214 [ # # ]: 0 : if (!new_object) { 215 : : return (AE_NO_MEMORY); 216 : : } 217 : : 218 : 0 : memcpy(new_object->buffer.pointer, 219 : 0 : original_object->string.pointer, 220 : 0 : original_object->string.length); 221 : 0 : break; 222 : : 223 : 0 : 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 : 0 : elements = original_object->package.elements; 233 : 0 : count = original_object->package.count; 234 : : 235 [ # # ]: 0 : for (i = 0; i < count; i++) { 236 [ # # ]: 0 : if ((!*elements) || 237 [ # # ]: 0 : ((*elements)->common.type != ACPI_TYPE_INTEGER)) { 238 : : return (AE_AML_OPERAND_TYPE); 239 : : } 240 : 0 : elements++; 241 : : } 242 : : 243 : : /* Create the new buffer object to replace the Package */ 244 : : 245 : 0 : new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); 246 [ # # ]: 0 : if (!new_object) { 247 : : return (AE_NO_MEMORY); 248 : : } 249 : : 250 : : /* Copy the package elements (integers) to the buffer as DWORDs */ 251 : : 252 : 0 : elements = original_object->package.elements; 253 : 0 : dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); 254 : : 255 [ # # ]: 0 : for (i = 0; i < count; i++) { 256 : 0 : *dword_buffer = (u32)(*elements)->integer.value; 257 : 0 : dword_buffer++; 258 : 0 : elements++; 259 : : } 260 : : break; 261 : : 262 : : default: 263 : : 264 : : return (AE_AML_OPERAND_TYPE); 265 : : } 266 : : 267 : 0 : *return_object = new_object; 268 : 0 : 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 : 0 : 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 : 0 : union acpi_operand_object *new_object; 291 : 0 : char *ascii_string; 292 : 0 : u16 *unicode_buffer; 293 : 0 : u32 unicode_length; 294 : 0 : u32 i; 295 : : 296 [ # # ]: 0 : 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 [ # # ]: 0 : if (original_object->common.type == ACPI_TYPE_BUFFER) { 303 [ # # ]: 0 : if (original_object->buffer.length < 2) { 304 : : return (AE_AML_OPERAND_VALUE); 305 : : } 306 : : 307 : 0 : *return_object = NULL; 308 : 0 : return (AE_OK); 309 : : } 310 : : 311 : : /* 312 : : * The original object is an ASCII string. Convert this string to 313 : : * a unicode buffer. 314 : : */ 315 : 0 : ascii_string = original_object->string.pointer; 316 : 0 : unicode_length = (original_object->string.length * 2) + 2; 317 : : 318 : : /* Create a new buffer object for the Unicode data */ 319 : : 320 : 0 : new_object = acpi_ut_create_buffer_object(unicode_length); 321 [ # # ]: 0 : if (!new_object) { 322 : : return (AE_NO_MEMORY); 323 : : } 324 : : 325 : 0 : unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer); 326 : : 327 : : /* Convert ASCII to Unicode */ 328 : : 329 [ # # ]: 0 : for (i = 0; i < original_object->string.length; i++) { 330 : 0 : unicode_buffer[i] = (u16)ascii_string[i]; 331 : : } 332 : : 333 : 0 : *return_object = new_object; 334 : 0 : 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 : 440 : 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 : 440 : union acpi_operand_object *new_object; 358 : 440 : 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 [ + - ]: 440 : if (original_object) { 370 [ - + - ]: 440 : switch (original_object->common.type) { 371 : 0 : case ACPI_TYPE_INTEGER: 372 : : 373 : : /* We can only repair an Integer==0 */ 374 : : 375 [ # # ]: 0 : if (original_object->integer.value) { 376 : : return (AE_AML_OPERAND_TYPE); 377 : : } 378 : : break; 379 : : 380 : 440 : case ACPI_TYPE_BUFFER: 381 : : 382 [ + - ]: 440 : if (original_object->buffer.length) { 383 : : 384 : : /* Additional checks can be added in the future */ 385 : : 386 : 440 : *return_object = NULL; 387 : 440 : return (AE_OK); 388 : : } 389 : : break; 390 : : 391 : : case ACPI_TYPE_STRING: 392 : : default: 393 : : 394 : : return (AE_AML_OPERAND_TYPE); 395 : : } 396 : 0 : } 397 : : 398 : : /* Create the new buffer object for the resource descriptor */ 399 : : 400 : 0 : new_object = acpi_ut_create_buffer_object(2); 401 [ # # ]: 0 : if (!new_object) { 402 : : return (AE_NO_MEMORY); 403 : : } 404 : : 405 : 0 : buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer); 406 : : 407 : : /* Initialize the Buffer with a single end_tag descriptor */ 408 : : 409 : 0 : buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); 410 : 0 : buffer[1] = 0x00; 411 : : 412 : 0 : *return_object = new_object; 413 : 0 : 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 : 0 : 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 : 0 : union acpi_operand_object *new_object = NULL; 437 : 0 : acpi_status status; 438 : 0 : struct acpi_namespace_node *node; 439 : 0 : union acpi_generic_state scope_info; 440 : 0 : char *name; 441 : : 442 : 0 : ACPI_FUNCTION_NAME(ns_convert_to_reference); 443 : : 444 : : /* Convert path into internal presentation */ 445 : : 446 : 0 : status = 447 : 0 : acpi_ns_internalize_name(original_object->string.pointer, &name); 448 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 449 : : return_ACPI_STATUS(status); 450 : : } 451 : : 452 : : /* Find the namespace node */ 453 : : 454 : 0 : scope_info.scope.node = 455 : : ACPI_CAST_PTR(struct acpi_namespace_node, scope); 456 : 0 : status = 457 : 0 : 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 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 461 : : 462 : : /* Check if we are resolving a named reference within a package */ 463 : : 464 : 0 : ACPI_ERROR_NAMESPACE(&scope_info, 465 : 0 : original_object->string.pointer, status); 466 : 0 : goto error_exit; 467 : : } 468 : : 469 : : /* Create and init a new internal ACPI object */ 470 : : 471 : 0 : new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); 472 [ # # ]: 0 : if (!new_object) { 473 : 0 : status = AE_NO_MEMORY; 474 : 0 : goto error_exit; 475 : : } 476 : 0 : new_object->reference.node = node; 477 : 0 : new_object->reference.object = node->object; 478 : 0 : 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 : 0 : acpi_ut_add_reference(node->object); 485 : : 486 : 0 : error_exit: 487 : 0 : ACPI_FREE(name); 488 : 0 : *return_object = new_object; 489 : 0 : return (status); 490 : : }