1 /****************************************************************************** 2 * 3 * Module Name: nsconvert - Object conversions for objects returned by 4 * predefined methods 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2013, 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, &value); 83 if (ACPI_FAILURE(status)) { 84 return (status); 85 } 86 break; 87 88 case ACPI_TYPE_BUFFER: 89 90 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ 91 92 if (original_object->buffer.length > 8) { 93 return (AE_AML_OPERAND_TYPE); 94 } 95 96 /* Extract each buffer byte to create the integer */ 97 98 for (i = 0; i < original_object->buffer.length; i++) { 99 value |= 100 ((u64)original_object->buffer. 101 pointer[i] << (i * 8)); 102 } 103 break; 104 105 default: 106 107 return (AE_AML_OPERAND_TYPE); 108 } 109 110 new_object = acpi_ut_create_integer_object(value); 111 if (!new_object) { 112 return (AE_NO_MEMORY); 113 } 114 115 *return_object = new_object; 116 return (AE_OK); 117 } 118 119 /******************************************************************************* 120 * 121 * FUNCTION: acpi_ns_convert_to_string 122 * 123 * PARAMETERS: original_object - Object to be converted 124 * return_object - Where the new converted object is returned 125 * 126 * RETURN: Status. AE_OK if conversion was successful. 127 * 128 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. 129 * 130 ******************************************************************************/ 131 132 acpi_status 133 acpi_ns_convert_to_string(union acpi_operand_object *original_object, 134 union acpi_operand_object **return_object) 135 { 136 union acpi_operand_object *new_object; 137 acpi_size length; 138 acpi_status status; 139 140 switch (original_object->common.type) { 141 case ACPI_TYPE_INTEGER: 142 /* 143 * Integer-to-String conversion. Commonly, convert 144 * an integer of value 0 to a NULL string. The last element of 145 * _BIF and _BIX packages occasionally need this fix. 146 */ 147 if (original_object->integer.value == 0) { 148 149 /* Allocate a new NULL string object */ 150 151 new_object = acpi_ut_create_string_object(0); 152 if (!new_object) { 153 return (AE_NO_MEMORY); 154 } 155 } else { 156 status = 157 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 ACPI_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 = 248 acpi_ut_create_buffer_object(original_object->string. 249 length); 250 if (!new_object) { 251 return (AE_NO_MEMORY); 252 } 253 254 ACPI_MEMCPY(new_object->buffer.pointer, 255 original_object->string.pointer, 256 original_object->string.length); 257 break; 258 259 case ACPI_TYPE_PACKAGE: 260 /* 261 * This case is often seen for predefined names that must return a 262 * Buffer object with multiple DWORD integers within. For example, 263 * _FDE and _GTM. The Package can be converted to a Buffer. 264 */ 265 266 /* All elements of the Package must be integers */ 267 268 elements = original_object->package.elements; 269 count = original_object->package.count; 270 271 for (i = 0; i < count; i++) { 272 if ((!*elements) || 273 ((*elements)->common.type != ACPI_TYPE_INTEGER)) { 274 return (AE_AML_OPERAND_TYPE); 275 } 276 elements++; 277 } 278 279 /* Create the new buffer object to replace the Package */ 280 281 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); 282 if (!new_object) { 283 return (AE_NO_MEMORY); 284 } 285 286 /* Copy the package elements (integers) to the buffer as DWORDs */ 287 288 elements = original_object->package.elements; 289 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); 290 291 for (i = 0; i < count; i++) { 292 *dword_buffer = (u32)(*elements)->integer.value; 293 dword_buffer++; 294 elements++; 295 } 296 break; 297 298 default: 299 300 return (AE_AML_OPERAND_TYPE); 301 } 302 303 *return_object = new_object; 304 return (AE_OK); 305 } 306 307 /******************************************************************************* 308 * 309 * FUNCTION: acpi_ns_convert_to_unicode 310 * 311 * PARAMETERS: 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(union acpi_operand_object *original_object, 322 union acpi_operand_object **return_object) 323 { 324 union acpi_operand_object *new_object; 325 char *ascii_string; 326 u16 *unicode_buffer; 327 u32 unicode_length; 328 u32 i; 329 330 if (!original_object) { 331 return (AE_OK); 332 } 333 334 /* If a Buffer was returned, it must be at least two bytes long */ 335 336 if (original_object->common.type == ACPI_TYPE_BUFFER) { 337 if (original_object->buffer.length < 2) { 338 return (AE_AML_OPERAND_VALUE); 339 } 340 341 *return_object = NULL; 342 return (AE_OK); 343 } 344 345 /* 346 * The original object is an ASCII string. Convert this string to 347 * a unicode buffer. 348 */ 349 ascii_string = original_object->string.pointer; 350 unicode_length = (original_object->string.length * 2) + 2; 351 352 /* Create a new buffer object for the Unicode data */ 353 354 new_object = acpi_ut_create_buffer_object(unicode_length); 355 if (!new_object) { 356 return (AE_NO_MEMORY); 357 } 358 359 unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer); 360 361 /* Convert ASCII to Unicode */ 362 363 for (i = 0; i < original_object->string.length; i++) { 364 unicode_buffer[i] = (u16)ascii_string[i]; 365 } 366 367 *return_object = new_object; 368 return (AE_OK); 369 } 370 371 /******************************************************************************* 372 * 373 * FUNCTION: acpi_ns_convert_to_resource 374 * 375 * PARAMETERS: original_object - Object to be converted 376 * return_object - Where the new converted object is returned 377 * 378 * RETURN: Status. AE_OK if conversion was successful 379 * 380 * DESCRIPTION: Attempt to convert a Integer object to a resource_template 381 * Buffer. 382 * 383 ******************************************************************************/ 384 385 acpi_status 386 acpi_ns_convert_to_resource(union acpi_operand_object *original_object, 387 union acpi_operand_object **return_object) 388 { 389 union acpi_operand_object *new_object; 390 u8 *buffer; 391 392 /* 393 * We can fix the following cases for an expected resource template: 394 * 1. No return value (interpreter slack mode is disabled) 395 * 2. A "Return (Zero)" statement 396 * 3. A "Return empty buffer" statement 397 * 398 * We will return a buffer containing a single end_tag 399 * resource descriptor. 400 */ 401 if (original_object) { 402 switch (original_object->common.type) { 403 case ACPI_TYPE_INTEGER: 404 405 /* We can only repair an Integer==0 */ 406 407 if (original_object->integer.value) { 408 return (AE_AML_OPERAND_TYPE); 409 } 410 break; 411 412 case ACPI_TYPE_BUFFER: 413 414 if (original_object->buffer.length) { 415 416 /* Additional checks can be added in the future */ 417 418 *return_object = NULL; 419 return (AE_OK); 420 } 421 break; 422 423 case ACPI_TYPE_STRING: 424 default: 425 426 return (AE_AML_OPERAND_TYPE); 427 } 428 } 429 430 /* Create the new buffer object for the resource descriptor */ 431 432 new_object = acpi_ut_create_buffer_object(2); 433 if (!new_object) { 434 return (AE_NO_MEMORY); 435 } 436 437 buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer); 438 439 /* Initialize the Buffer with a single end_tag descriptor */ 440 441 buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); 442 buffer[1] = 0x00; 443 444 *return_object = new_object; 445 return (AE_OK); 446 } 447