1 /****************************************************************************** 2 * 3 * Module Name: nsconvert - Object conversions for objects returned by 4 * predefined methods 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2016, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #include <acpi/acpi.h> 46 #include "accommon.h" 47 #include "acnamesp.h" 48 #include "acinterp.h" 49 #include "acpredef.h" 50 #include "amlresrc.h" 51 52 #define _COMPONENT ACPI_NAMESPACE 53 ACPI_MODULE_NAME("nsconvert") 54 55 /******************************************************************************* 56 * 57 * FUNCTION: acpi_ns_convert_to_integer 58 * 59 * PARAMETERS: original_object - Object to be converted 60 * return_object - Where the new converted object is returned 61 * 62 * RETURN: Status. AE_OK if conversion was successful. 63 * 64 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. 65 * 66 ******************************************************************************/ 67 acpi_status 68 acpi_ns_convert_to_integer(union acpi_operand_object *original_object, 69 union acpi_operand_object **return_object) 70 { 71 union acpi_operand_object *new_object; 72 acpi_status status; 73 u64 value = 0; 74 u32 i; 75 76 switch (original_object->common.type) { 77 case ACPI_TYPE_STRING: 78 79 /* String-to-Integer conversion */ 80 81 status = acpi_ut_strtoul64(original_object->string.pointer, 82 ACPI_ANY_BASE, 83 acpi_gbl_integer_byte_width, &value); 84 if (ACPI_FAILURE(status)) { 85 return (status); 86 } 87 break; 88 89 case ACPI_TYPE_BUFFER: 90 91 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ 92 93 if (original_object->buffer.length > 8) { 94 return (AE_AML_OPERAND_TYPE); 95 } 96 97 /* Extract each buffer byte to create the integer */ 98 99 for (i = 0; i < original_object->buffer.length; i++) { 100 value |= ((u64) 101 original_object->buffer.pointer[i] << (i * 102 8)); 103 } 104 break; 105 106 default: 107 108 return (AE_AML_OPERAND_TYPE); 109 } 110 111 new_object = acpi_ut_create_integer_object(value); 112 if (!new_object) { 113 return (AE_NO_MEMORY); 114 } 115 116 *return_object = new_object; 117 return (AE_OK); 118 } 119 120 /******************************************************************************* 121 * 122 * FUNCTION: acpi_ns_convert_to_string 123 * 124 * PARAMETERS: original_object - Object to be converted 125 * return_object - Where the new converted object is returned 126 * 127 * RETURN: Status. AE_OK if conversion was successful. 128 * 129 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. 130 * 131 ******************************************************************************/ 132 133 acpi_status 134 acpi_ns_convert_to_string(union acpi_operand_object *original_object, 135 union acpi_operand_object **return_object) 136 { 137 union acpi_operand_object *new_object; 138 acpi_size length; 139 acpi_status status; 140 141 switch (original_object->common.type) { 142 case ACPI_TYPE_INTEGER: 143 /* 144 * Integer-to-String conversion. Commonly, convert 145 * an integer of value 0 to a NULL string. The last element of 146 * _BIF and _BIX packages occasionally need this fix. 147 */ 148 if (original_object->integer.value == 0) { 149 150 /* Allocate a new NULL string object */ 151 152 new_object = acpi_ut_create_string_object(0); 153 if (!new_object) { 154 return (AE_NO_MEMORY); 155 } 156 } else { 157 status = acpi_ex_convert_to_string(original_object, 158 &new_object, 159 ACPI_IMPLICIT_CONVERT_HEX); 160 if (ACPI_FAILURE(status)) { 161 return (status); 162 } 163 } 164 break; 165 166 case ACPI_TYPE_BUFFER: 167 /* 168 * Buffer-to-String conversion. Use a to_string 169 * conversion, no transform performed on the buffer data. The best 170 * example of this is the _BIF method, where the string data from 171 * the battery is often (incorrectly) returned as buffer object(s). 172 */ 173 length = 0; 174 while ((length < original_object->buffer.length) && 175 (original_object->buffer.pointer[length])) { 176 length++; 177 } 178 179 /* Allocate a new string object */ 180 181 new_object = acpi_ut_create_string_object(length); 182 if (!new_object) { 183 return (AE_NO_MEMORY); 184 } 185 186 /* 187 * Copy the raw buffer data with no transform. String is already NULL 188 * terminated at Length+1. 189 */ 190 memcpy(new_object->string.pointer, 191 original_object->buffer.pointer, length); 192 break; 193 194 default: 195 196 return (AE_AML_OPERAND_TYPE); 197 } 198 199 *return_object = new_object; 200 return (AE_OK); 201 } 202 203 /******************************************************************************* 204 * 205 * FUNCTION: acpi_ns_convert_to_buffer 206 * 207 * PARAMETERS: original_object - Object to be converted 208 * return_object - Where the new converted object is returned 209 * 210 * RETURN: Status. AE_OK if conversion was successful. 211 * 212 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. 213 * 214 ******************************************************************************/ 215 216 acpi_status 217 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 218 union acpi_operand_object **return_object) 219 { 220 union acpi_operand_object *new_object; 221 acpi_status status; 222 union acpi_operand_object **elements; 223 u32 *dword_buffer; 224 u32 count; 225 u32 i; 226 227 switch (original_object->common.type) { 228 case ACPI_TYPE_INTEGER: 229 /* 230 * Integer-to-Buffer conversion. 231 * Convert the Integer to a packed-byte buffer. _MAT and other 232 * objects need this sometimes, if a read has been performed on a 233 * Field object that is less than or equal to the global integer 234 * size (32 or 64 bits). 235 */ 236 status = 237 acpi_ex_convert_to_buffer(original_object, &new_object); 238 if (ACPI_FAILURE(status)) { 239 return (status); 240 } 241 break; 242 243 case ACPI_TYPE_STRING: 244 245 /* String-to-Buffer conversion. Simple data copy */ 246 247 new_object = acpi_ut_create_buffer_object 248 (original_object->string.length); 249 if (!new_object) { 250 return (AE_NO_MEMORY); 251 } 252 253 memcpy(new_object->buffer.pointer, 254 original_object->string.pointer, 255 original_object->string.length); 256 break; 257 258 case ACPI_TYPE_PACKAGE: 259 /* 260 * This case is often seen for predefined names that must return a 261 * Buffer object with multiple DWORD integers within. For example, 262 * _FDE and _GTM. The Package can be converted to a Buffer. 263 */ 264 265 /* All elements of the Package must be integers */ 266 267 elements = original_object->package.elements; 268 count = original_object->package.count; 269 270 for (i = 0; i < count; i++) { 271 if ((!*elements) || 272 ((*elements)->common.type != ACPI_TYPE_INTEGER)) { 273 return (AE_AML_OPERAND_TYPE); 274 } 275 elements++; 276 } 277 278 /* Create the new buffer object to replace the Package */ 279 280 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); 281 if (!new_object) { 282 return (AE_NO_MEMORY); 283 } 284 285 /* Copy the package elements (integers) to the buffer as DWORDs */ 286 287 elements = original_object->package.elements; 288 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); 289 290 for (i = 0; i < count; i++) { 291 *dword_buffer = (u32)(*elements)->integer.value; 292 dword_buffer++; 293 elements++; 294 } 295 break; 296 297 default: 298 299 return (AE_AML_OPERAND_TYPE); 300 } 301 302 *return_object = new_object; 303 return (AE_OK); 304 } 305 306 /******************************************************************************* 307 * 308 * FUNCTION: acpi_ns_convert_to_unicode 309 * 310 * PARAMETERS: scope - Namespace node for the method/object 311 * original_object - ASCII String Object to be converted 312 * return_object - Where the new converted object is returned 313 * 314 * RETURN: Status. AE_OK if conversion was successful. 315 * 316 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer. 317 * 318 ******************************************************************************/ 319 320 acpi_status 321 acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope, 322 union acpi_operand_object *original_object, 323 union acpi_operand_object **return_object) 324 { 325 union acpi_operand_object *new_object; 326 char *ascii_string; 327 u16 *unicode_buffer; 328 u32 unicode_length; 329 u32 i; 330 331 if (!original_object) { 332 return (AE_OK); 333 } 334 335 /* If a Buffer was returned, it must be at least two bytes long */ 336 337 if (original_object->common.type == ACPI_TYPE_BUFFER) { 338 if (original_object->buffer.length < 2) { 339 return (AE_AML_OPERAND_VALUE); 340 } 341 342 *return_object = NULL; 343 return (AE_OK); 344 } 345 346 /* 347 * The original object is an ASCII string. Convert this string to 348 * a unicode buffer. 349 */ 350 ascii_string = original_object->string.pointer; 351 unicode_length = (original_object->string.length * 2) + 2; 352 353 /* Create a new buffer object for the Unicode data */ 354 355 new_object = acpi_ut_create_buffer_object(unicode_length); 356 if (!new_object) { 357 return (AE_NO_MEMORY); 358 } 359 360 unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer); 361 362 /* Convert ASCII to Unicode */ 363 364 for (i = 0; i < original_object->string.length; i++) { 365 unicode_buffer[i] = (u16)ascii_string[i]; 366 } 367 368 *return_object = new_object; 369 return (AE_OK); 370 } 371 372 /******************************************************************************* 373 * 374 * FUNCTION: acpi_ns_convert_to_resource 375 * 376 * PARAMETERS: scope - Namespace node for the method/object 377 * original_object - Object to be converted 378 * return_object - Where the new converted object is returned 379 * 380 * RETURN: Status. AE_OK if conversion was successful 381 * 382 * DESCRIPTION: Attempt to convert a Integer object to a resource_template 383 * Buffer. 384 * 385 ******************************************************************************/ 386 387 acpi_status 388 acpi_ns_convert_to_resource(struct acpi_namespace_node *scope, 389 union acpi_operand_object *original_object, 390 union acpi_operand_object **return_object) 391 { 392 union acpi_operand_object *new_object; 393 u8 *buffer; 394 395 /* 396 * We can fix the following cases for an expected resource template: 397 * 1. No return value (interpreter slack mode is disabled) 398 * 2. A "Return (Zero)" statement 399 * 3. A "Return empty buffer" statement 400 * 401 * We will return a buffer containing a single end_tag 402 * resource descriptor. 403 */ 404 if (original_object) { 405 switch (original_object->common.type) { 406 case ACPI_TYPE_INTEGER: 407 408 /* We can only repair an Integer==0 */ 409 410 if (original_object->integer.value) { 411 return (AE_AML_OPERAND_TYPE); 412 } 413 break; 414 415 case ACPI_TYPE_BUFFER: 416 417 if (original_object->buffer.length) { 418 419 /* Additional checks can be added in the future */ 420 421 *return_object = NULL; 422 return (AE_OK); 423 } 424 break; 425 426 case ACPI_TYPE_STRING: 427 default: 428 429 return (AE_AML_OPERAND_TYPE); 430 } 431 } 432 433 /* Create the new buffer object for the resource descriptor */ 434 435 new_object = acpi_ut_create_buffer_object(2); 436 if (!new_object) { 437 return (AE_NO_MEMORY); 438 } 439 440 buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer); 441 442 /* Initialize the Buffer with a single end_tag descriptor */ 443 444 buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); 445 buffer[1] = 0x00; 446 447 *return_object = new_object; 448 return (AE_OK); 449 } 450 451 /******************************************************************************* 452 * 453 * FUNCTION: acpi_ns_convert_to_reference 454 * 455 * PARAMETERS: scope - Namespace node for the method/object 456 * original_object - Object to be converted 457 * return_object - Where the new converted object is returned 458 * 459 * RETURN: Status. AE_OK if conversion was successful 460 * 461 * DESCRIPTION: Attempt to convert a Integer object to a object_reference. 462 * Buffer. 463 * 464 ******************************************************************************/ 465 466 acpi_status 467 acpi_ns_convert_to_reference(struct acpi_namespace_node *scope, 468 union acpi_operand_object *original_object, 469 union acpi_operand_object **return_object) 470 { 471 union acpi_operand_object *new_object = NULL; 472 acpi_status status; 473 struct acpi_namespace_node *node; 474 union acpi_generic_state scope_info; 475 char *name; 476 477 ACPI_FUNCTION_NAME(ns_convert_to_reference); 478 479 /* Convert path into internal presentation */ 480 481 status = 482 acpi_ns_internalize_name(original_object->string.pointer, &name); 483 if (ACPI_FAILURE(status)) { 484 return_ACPI_STATUS(status); 485 } 486 487 /* Find the namespace node */ 488 489 scope_info.scope.node = 490 ACPI_CAST_PTR(struct acpi_namespace_node, scope); 491 status = 492 acpi_ns_lookup(&scope_info, name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 493 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 494 NULL, &node); 495 if (ACPI_FAILURE(status)) { 496 497 /* Check if we are resolving a named reference within a package */ 498 499 ACPI_ERROR_NAMESPACE(original_object->string.pointer, status); 500 goto error_exit; 501 } 502 503 /* Create and init a new internal ACPI object */ 504 505 new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); 506 if (!new_object) { 507 status = AE_NO_MEMORY; 508 goto error_exit; 509 } 510 new_object->reference.node = node; 511 new_object->reference.object = node->object; 512 new_object->reference.class = ACPI_REFCLASS_NAME; 513 514 /* 515 * Increase reference of the object if needed (the object is likely a 516 * null for device nodes). 517 */ 518 acpi_ut_add_reference(node->object); 519 520 error_exit: 521 ACPI_FREE(name); 522 *return_object = new_object; 523 return (AE_OK); 524 } 525