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 #define __NSCONVERT_C__ 46 47 #include <contrib/dev/acpica/include/acpi.h> 48 #include <contrib/dev/acpica/include/accommon.h> 49 #include <contrib/dev/acpica/include/acnamesp.h> 50 #include <contrib/dev/acpica/include/acinterp.h> 51 #include <contrib/dev/acpica/include/acpredef.h> 52 #include <contrib/dev/acpica/include/amlresrc.h> 53 54 #define _COMPONENT ACPI_NAMESPACE 55 ACPI_MODULE_NAME ("nsconvert") 56 57 58 /******************************************************************************* 59 * 60 * FUNCTION: AcpiNsConvertToInteger 61 * 62 * PARAMETERS: OriginalObject - Object to be converted 63 * ReturnObject - Where the new converted object is returned 64 * 65 * RETURN: Status. AE_OK if conversion was successful. 66 * 67 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. 68 * 69 ******************************************************************************/ 70 71 ACPI_STATUS 72 AcpiNsConvertToInteger ( 73 ACPI_OPERAND_OBJECT *OriginalObject, 74 ACPI_OPERAND_OBJECT **ReturnObject) 75 { 76 ACPI_OPERAND_OBJECT *NewObject; 77 ACPI_STATUS Status; 78 UINT64 Value = 0; 79 UINT32 i; 80 81 82 switch (OriginalObject->Common.Type) 83 { 84 case ACPI_TYPE_STRING: 85 86 /* String-to-Integer conversion */ 87 88 Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer, 89 ACPI_ANY_BASE, &Value); 90 if (ACPI_FAILURE (Status)) 91 { 92 return (Status); 93 } 94 break; 95 96 case ACPI_TYPE_BUFFER: 97 98 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ 99 100 if (OriginalObject->Buffer.Length > 8) 101 { 102 return (AE_AML_OPERAND_TYPE); 103 } 104 105 /* Extract each buffer byte to create the integer */ 106 107 for (i = 0; i < OriginalObject->Buffer.Length; i++) 108 { 109 Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8)); 110 } 111 break; 112 113 default: 114 return (AE_AML_OPERAND_TYPE); 115 } 116 117 NewObject = AcpiUtCreateIntegerObject (Value); 118 if (!NewObject) 119 { 120 return (AE_NO_MEMORY); 121 } 122 123 *ReturnObject = NewObject; 124 return (AE_OK); 125 } 126 127 128 /******************************************************************************* 129 * 130 * FUNCTION: AcpiNsConvertToString 131 * 132 * PARAMETERS: OriginalObject - Object to be converted 133 * ReturnObject - Where the new converted object is returned 134 * 135 * RETURN: Status. AE_OK if conversion was successful. 136 * 137 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. 138 * 139 ******************************************************************************/ 140 141 ACPI_STATUS 142 AcpiNsConvertToString ( 143 ACPI_OPERAND_OBJECT *OriginalObject, 144 ACPI_OPERAND_OBJECT **ReturnObject) 145 { 146 ACPI_OPERAND_OBJECT *NewObject; 147 ACPI_SIZE Length; 148 ACPI_STATUS Status; 149 150 151 switch (OriginalObject->Common.Type) 152 { 153 case ACPI_TYPE_INTEGER: 154 /* 155 * Integer-to-String conversion. Commonly, convert 156 * an integer of value 0 to a NULL string. The last element of 157 * _BIF and _BIX packages occasionally need this fix. 158 */ 159 if (OriginalObject->Integer.Value == 0) 160 { 161 /* Allocate a new NULL string object */ 162 163 NewObject = AcpiUtCreateStringObject (0); 164 if (!NewObject) 165 { 166 return (AE_NO_MEMORY); 167 } 168 } 169 else 170 { 171 Status = AcpiExConvertToString (OriginalObject, &NewObject, 172 ACPI_IMPLICIT_CONVERT_HEX); 173 if (ACPI_FAILURE (Status)) 174 { 175 return (Status); 176 } 177 } 178 break; 179 180 case ACPI_TYPE_BUFFER: 181 /* 182 * Buffer-to-String conversion. Use a ToString 183 * conversion, no transform performed on the buffer data. The best 184 * example of this is the _BIF method, where the string data from 185 * the battery is often (incorrectly) returned as buffer object(s). 186 */ 187 Length = 0; 188 while ((Length < OriginalObject->Buffer.Length) && 189 (OriginalObject->Buffer.Pointer[Length])) 190 { 191 Length++; 192 } 193 194 /* Allocate a new string object */ 195 196 NewObject = AcpiUtCreateStringObject (Length); 197 if (!NewObject) 198 { 199 return (AE_NO_MEMORY); 200 } 201 202 /* 203 * Copy the raw buffer data with no transform. String is already NULL 204 * terminated at Length+1. 205 */ 206 ACPI_MEMCPY (NewObject->String.Pointer, 207 OriginalObject->Buffer.Pointer, Length); 208 break; 209 210 default: 211 return (AE_AML_OPERAND_TYPE); 212 } 213 214 *ReturnObject = NewObject; 215 return (AE_OK); 216 } 217 218 219 /******************************************************************************* 220 * 221 * FUNCTION: AcpiNsConvertToBuffer 222 * 223 * PARAMETERS: OriginalObject - Object to be converted 224 * ReturnObject - Where the new converted object is returned 225 * 226 * RETURN: Status. AE_OK if conversion was successful. 227 * 228 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. 229 * 230 ******************************************************************************/ 231 232 ACPI_STATUS 233 AcpiNsConvertToBuffer ( 234 ACPI_OPERAND_OBJECT *OriginalObject, 235 ACPI_OPERAND_OBJECT **ReturnObject) 236 { 237 ACPI_OPERAND_OBJECT *NewObject; 238 ACPI_STATUS Status; 239 ACPI_OPERAND_OBJECT **Elements; 240 UINT32 *DwordBuffer; 241 UINT32 Count; 242 UINT32 i; 243 244 245 switch (OriginalObject->Common.Type) 246 { 247 case ACPI_TYPE_INTEGER: 248 /* 249 * Integer-to-Buffer conversion. 250 * Convert the Integer to a packed-byte buffer. _MAT and other 251 * objects need this sometimes, if a read has been performed on a 252 * Field object that is less than or equal to the global integer 253 * size (32 or 64 bits). 254 */ 255 Status = AcpiExConvertToBuffer (OriginalObject, &NewObject); 256 if (ACPI_FAILURE (Status)) 257 { 258 return (Status); 259 } 260 break; 261 262 case ACPI_TYPE_STRING: 263 264 /* String-to-Buffer conversion. Simple data copy */ 265 266 NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length); 267 if (!NewObject) 268 { 269 return (AE_NO_MEMORY); 270 } 271 272 ACPI_MEMCPY (NewObject->Buffer.Pointer, 273 OriginalObject->String.Pointer, OriginalObject->String.Length); 274 break; 275 276 case ACPI_TYPE_PACKAGE: 277 /* 278 * This case is often seen for predefined names that must return a 279 * Buffer object with multiple DWORD integers within. For example, 280 * _FDE and _GTM. The Package can be converted to a Buffer. 281 */ 282 283 /* All elements of the Package must be integers */ 284 285 Elements = OriginalObject->Package.Elements; 286 Count = OriginalObject->Package.Count; 287 288 for (i = 0; i < Count; i++) 289 { 290 if ((!*Elements) || 291 ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)) 292 { 293 return (AE_AML_OPERAND_TYPE); 294 } 295 Elements++; 296 } 297 298 /* Create the new buffer object to replace the Package */ 299 300 NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count)); 301 if (!NewObject) 302 { 303 return (AE_NO_MEMORY); 304 } 305 306 /* Copy the package elements (integers) to the buffer as DWORDs */ 307 308 Elements = OriginalObject->Package.Elements; 309 DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer); 310 311 for (i = 0; i < Count; i++) 312 { 313 *DwordBuffer = (UINT32) (*Elements)->Integer.Value; 314 DwordBuffer++; 315 Elements++; 316 } 317 break; 318 319 default: 320 return (AE_AML_OPERAND_TYPE); 321 } 322 323 *ReturnObject = NewObject; 324 return (AE_OK); 325 } 326 327 328 /******************************************************************************* 329 * 330 * FUNCTION: AcpiNsConvertToUnicode 331 * 332 * PARAMETERS: OriginalObject - ASCII String Object to be converted 333 * ReturnObject - Where the new converted object is returned 334 * 335 * RETURN: Status. AE_OK if conversion was successful. 336 * 337 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer. 338 * 339 ******************************************************************************/ 340 341 ACPI_STATUS 342 AcpiNsConvertToUnicode ( 343 ACPI_OPERAND_OBJECT *OriginalObject, 344 ACPI_OPERAND_OBJECT **ReturnObject) 345 { 346 ACPI_OPERAND_OBJECT *NewObject; 347 char *AsciiString; 348 UINT16 *UnicodeBuffer; 349 UINT32 UnicodeLength; 350 UINT32 i; 351 352 353 if (!OriginalObject) 354 { 355 return (AE_OK); 356 } 357 358 /* If a Buffer was returned, it must be at least two bytes long */ 359 360 if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER) 361 { 362 if (OriginalObject->Buffer.Length < 2) 363 { 364 return (AE_AML_OPERAND_VALUE); 365 } 366 367 *ReturnObject = NULL; 368 return (AE_OK); 369 } 370 371 /* 372 * The original object is an ASCII string. Convert this string to 373 * a unicode buffer. 374 */ 375 AsciiString = OriginalObject->String.Pointer; 376 UnicodeLength = (OriginalObject->String.Length * 2) + 2; 377 378 /* Create a new buffer object for the Unicode data */ 379 380 NewObject = AcpiUtCreateBufferObject (UnicodeLength); 381 if (!NewObject) 382 { 383 return (AE_NO_MEMORY); 384 } 385 386 UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer); 387 388 /* Convert ASCII to Unicode */ 389 390 for (i = 0; i < OriginalObject->String.Length; i++) 391 { 392 UnicodeBuffer[i] = (UINT16) AsciiString[i]; 393 } 394 395 *ReturnObject = NewObject; 396 return (AE_OK); 397 } 398 399 400 /******************************************************************************* 401 * 402 * FUNCTION: AcpiNsConvertToResource 403 * 404 * PARAMETERS: OriginalObject - Object to be converted 405 * ReturnObject - Where the new converted object is returned 406 * 407 * RETURN: Status. AE_OK if conversion was successful 408 * 409 * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate 410 * Buffer. 411 * 412 ******************************************************************************/ 413 414 ACPI_STATUS 415 AcpiNsConvertToResource ( 416 ACPI_OPERAND_OBJECT *OriginalObject, 417 ACPI_OPERAND_OBJECT **ReturnObject) 418 { 419 ACPI_OPERAND_OBJECT *NewObject; 420 UINT8 *Buffer; 421 422 423 /* 424 * We can fix the following cases for an expected resource template: 425 * 1. No return value (interpreter slack mode is disabled) 426 * 2. A "Return (Zero)" statement 427 * 3. A "Return empty buffer" statement 428 * 429 * We will return a buffer containing a single EndTag 430 * resource descriptor. 431 */ 432 if (OriginalObject) 433 { 434 switch (OriginalObject->Common.Type) 435 { 436 case ACPI_TYPE_INTEGER: 437 438 /* We can only repair an Integer==0 */ 439 440 if (OriginalObject->Integer.Value) 441 { 442 return (AE_AML_OPERAND_TYPE); 443 } 444 break; 445 446 case ACPI_TYPE_BUFFER: 447 448 if (OriginalObject->Buffer.Length) 449 { 450 /* Additional checks can be added in the future */ 451 452 *ReturnObject = NULL; 453 return (AE_OK); 454 } 455 break; 456 457 case ACPI_TYPE_STRING: 458 default: 459 460 return (AE_AML_OPERAND_TYPE); 461 } 462 } 463 464 /* Create the new buffer object for the resource descriptor */ 465 466 NewObject = AcpiUtCreateBufferObject (2); 467 if (!NewObject) 468 { 469 return (AE_NO_MEMORY); 470 } 471 472 Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer); 473 474 /* Initialize the Buffer with a single EndTag descriptor */ 475 476 Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); 477 Buffer[1] = 0x00; 478 479 *ReturnObject = NewObject; 480 return (AE_OK); 481 } 482