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