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 return (AE_AML_OPERAND_TYPE); 107 } 108 109 new_object = acpi_ut_create_integer_object(value); 110 if (!new_object) { 111 return (AE_NO_MEMORY); 112 } 113 114 *return_object = new_object; 115 return (AE_OK); 116 } 117 118 /******************************************************************************* 119 * 120 * FUNCTION: acpi_ns_convert_to_string 121 * 122 * PARAMETERS: original_object - Object to be converted 123 * return_object - Where the new converted object is returned 124 * 125 * RETURN: Status. AE_OK if conversion was successful. 126 * 127 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. 128 * 129 ******************************************************************************/ 130 131 acpi_status 132 acpi_ns_convert_to_string(union acpi_operand_object *original_object, 133 union acpi_operand_object **return_object) 134 { 135 union acpi_operand_object *new_object; 136 acpi_size length; 137 acpi_status status; 138 139 switch (original_object->common.type) { 140 case ACPI_TYPE_INTEGER: 141 /* 142 * Integer-to-String conversion. Commonly, convert 143 * an integer of value 0 to a NULL string. The last element of 144 * _BIF and _BIX packages occasionally need this fix. 145 */ 146 if (original_object->integer.value == 0) { 147 148 /* Allocate a new NULL string object */ 149 150 new_object = acpi_ut_create_string_object(0); 151 if (!new_object) { 152 return (AE_NO_MEMORY); 153 } 154 } else { 155 status = 156 acpi_ex_convert_to_string(original_object, 157 &new_object, 158 ACPI_IMPLICIT_CONVERT_HEX); 159 if (ACPI_FAILURE(status)) { 160 return (status); 161 } 162 } 163 break; 164 165 case ACPI_TYPE_BUFFER: 166 /* 167 * Buffer-to-String conversion. Use a to_string 168 * conversion, no transform performed on the buffer data. The best 169 * example of this is the _BIF method, where the string data from 170 * the battery is often (incorrectly) returned as buffer object(s). 171 */ 172 length = 0; 173 while ((length < original_object->buffer.length) && 174 (original_object->buffer.pointer[length])) { 175 length++; 176 } 177 178 /* Allocate a new string object */ 179 180 new_object = acpi_ut_create_string_object(length); 181 if (!new_object) { 182 return (AE_NO_MEMORY); 183 } 184 185 /* 186 * Copy the raw buffer data with no transform. String is already NULL 187 * terminated at Length+1. 188 */ 189 ACPI_MEMCPY(new_object->string.pointer, 190 original_object->buffer.pointer, length); 191 break; 192 193 default: 194 return (AE_AML_OPERAND_TYPE); 195 } 196 197 *return_object = new_object; 198 return (AE_OK); 199 } 200 201 /******************************************************************************* 202 * 203 * FUNCTION: acpi_ns_convert_to_buffer 204 * 205 * PARAMETERS: original_object - Object to be converted 206 * return_object - Where the new converted object is returned 207 * 208 * RETURN: Status. AE_OK if conversion was successful. 209 * 210 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. 211 * 212 ******************************************************************************/ 213 214 acpi_status 215 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 216 union acpi_operand_object **return_object) 217 { 218 union acpi_operand_object *new_object; 219 acpi_status status; 220 union acpi_operand_object **elements; 221 u32 *dword_buffer; 222 u32 count; 223 u32 i; 224 225 switch (original_object->common.type) { 226 case ACPI_TYPE_INTEGER: 227 /* 228 * Integer-to-Buffer conversion. 229 * Convert the Integer to a packed-byte buffer. _MAT and other 230 * objects need this sometimes, if a read has been performed on a 231 * Field object that is less than or equal to the global integer 232 * size (32 or 64 bits). 233 */ 234 status = 235 acpi_ex_convert_to_buffer(original_object, &new_object); 236 if (ACPI_FAILURE(status)) { 237 return (status); 238 } 239 break; 240 241 case ACPI_TYPE_STRING: 242 243 /* String-to-Buffer conversion. Simple data copy */ 244 245 new_object = 246 acpi_ut_create_buffer_object(original_object->string. 247 length); 248 if (!new_object) { 249 return (AE_NO_MEMORY); 250 } 251 252 ACPI_MEMCPY(new_object->buffer.pointer, 253 original_object->string.pointer, 254 original_object->string.length); 255 break; 256 257 case ACPI_TYPE_PACKAGE: 258 /* 259 * This case is often seen for predefined names that must return a 260 * Buffer object with multiple DWORD integers within. For example, 261 * _FDE and _GTM. The Package can be converted to a Buffer. 262 */ 263 264 /* All elements of the Package must be integers */ 265 266 elements = original_object->package.elements; 267 count = original_object->package.count; 268 269 for (i = 0; i < count; i++) { 270 if ((!*elements) || 271 ((*elements)->common.type != ACPI_TYPE_INTEGER)) { 272 return (AE_AML_OPERAND_TYPE); 273 } 274 elements++; 275 } 276 277 /* Create the new buffer object to replace the Package */ 278 279 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count)); 280 if (!new_object) { 281 return (AE_NO_MEMORY); 282 } 283 284 /* Copy the package elements (integers) to the buffer as DWORDs */ 285 286 elements = original_object->package.elements; 287 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer); 288 289 for (i = 0; i < count; i++) { 290 *dword_buffer = (u32)(*elements)->integer.value; 291 dword_buffer++; 292 elements++; 293 } 294 break; 295 296 default: 297 return (AE_AML_OPERAND_TYPE); 298 } 299 300 *return_object = new_object; 301 return (AE_OK); 302 } 303 304 /******************************************************************************* 305 * 306 * FUNCTION: acpi_ns_convert_to_unicode 307 * 308 * PARAMETERS: original_object - ASCII String Object to be converted 309 * return_object - Where the new converted object is returned 310 * 311 * RETURN: Status. AE_OK if conversion was successful. 312 * 313 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer. 314 * 315 ******************************************************************************/ 316 317 acpi_status 318 acpi_ns_convert_to_unicode(union acpi_operand_object *original_object, 319 union acpi_operand_object **return_object) 320 { 321 union acpi_operand_object *new_object; 322 char *ascii_string; 323 u16 *unicode_buffer; 324 u32 unicode_length; 325 u32 i; 326 327 if (!original_object) { 328 return (AE_OK); 329 } 330 331 /* If a Buffer was returned, it must be at least two bytes long */ 332 333 if (original_object->common.type == ACPI_TYPE_BUFFER) { 334 if (original_object->buffer.length < 2) { 335 return (AE_AML_OPERAND_VALUE); 336 } 337 338 *return_object = NULL; 339 return (AE_OK); 340 } 341 342 /* 343 * The original object is an ASCII string. Convert this string to 344 * a unicode buffer. 345 */ 346 ascii_string = original_object->string.pointer; 347 unicode_length = (original_object->string.length * 2) + 2; 348 349 /* Create a new buffer object for the Unicode data */ 350 351 new_object = acpi_ut_create_buffer_object(unicode_length); 352 if (!new_object) { 353 return (AE_NO_MEMORY); 354 } 355 356 unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer); 357 358 /* Convert ASCII to Unicode */ 359 360 for (i = 0; i < original_object->string.length; i++) { 361 unicode_buffer[i] = (u16)ascii_string[i]; 362 } 363 364 *return_object = new_object; 365 return (AE_OK); 366 } 367 368 /******************************************************************************* 369 * 370 * FUNCTION: acpi_ns_convert_to_resource 371 * 372 * PARAMETERS: original_object - Object to be converted 373 * return_object - Where the new converted object is returned 374 * 375 * RETURN: Status. AE_OK if conversion was successful 376 * 377 * DESCRIPTION: Attempt to convert a Integer object to a resource_template 378 * Buffer. 379 * 380 ******************************************************************************/ 381 382 acpi_status 383 acpi_ns_convert_to_resource(union acpi_operand_object *original_object, 384 union acpi_operand_object **return_object) 385 { 386 union acpi_operand_object *new_object; 387 u8 *buffer; 388 389 /* 390 * We can fix the following cases for an expected resource template: 391 * 1. No return value (interpreter slack mode is disabled) 392 * 2. A "Return (Zero)" statement 393 * 3. A "Return empty buffer" statement 394 * 395 * We will return a buffer containing a single end_tag 396 * resource descriptor. 397 */ 398 if (original_object) { 399 switch (original_object->common.type) { 400 case ACPI_TYPE_INTEGER: 401 402 /* We can only repair an Integer==0 */ 403 404 if (original_object->integer.value) { 405 return (AE_AML_OPERAND_TYPE); 406 } 407 break; 408 409 case ACPI_TYPE_BUFFER: 410 411 if (original_object->buffer.length) { 412 413 /* Additional checks can be added in the future */ 414 415 *return_object = NULL; 416 return (AE_OK); 417 } 418 break; 419 420 case ACPI_TYPE_STRING: 421 default: 422 423 return (AE_AML_OPERAND_TYPE); 424 } 425 } 426 427 /* Create the new buffer object for the resource descriptor */ 428 429 new_object = acpi_ut_create_buffer_object(2); 430 if (!new_object) { 431 return (AE_NO_MEMORY); 432 } 433 434 buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer); 435 436 /* Initialize the Buffer with a single end_tag descriptor */ 437 438 buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); 439 buffer[1] = 0x00; 440 441 *return_object = new_object; 442 return (AE_OK); 443 } 444