1 /****************************************************************************** 2 * 3 * Module Name: nsconvert - Object conversions for objects returned by 4 * predefined methods 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2015, 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 <contrib/dev/acpica/include/acpi.h> 46 #include <contrib/dev/acpica/include/accommon.h> 47 #include <contrib/dev/acpica/include/acnamesp.h> 48 #include <contrib/dev/acpica/include/acinterp.h> 49 #include <contrib/dev/acpica/include/acpredef.h> 50 #include <contrib/dev/acpica/include/amlresrc.h> 51 52 #define _COMPONENT ACPI_NAMESPACE 53 ACPI_MODULE_NAME ("nsconvert") 54 55 56 /******************************************************************************* 57 * 58 * FUNCTION: AcpiNsConvertToInteger 59 * 60 * PARAMETERS: OriginalObject - Object to be converted 61 * ReturnObject - Where the new converted object is returned 62 * 63 * RETURN: Status. AE_OK if conversion was successful. 64 * 65 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. 66 * 67 ******************************************************************************/ 68 69 ACPI_STATUS 70 AcpiNsConvertToInteger ( 71 ACPI_OPERAND_OBJECT *OriginalObject, 72 ACPI_OPERAND_OBJECT **ReturnObject) 73 { 74 ACPI_OPERAND_OBJECT *NewObject; 75 ACPI_STATUS Status; 76 UINT64 Value = 0; 77 UINT32 i; 78 79 80 switch (OriginalObject->Common.Type) 81 { 82 case ACPI_TYPE_STRING: 83 84 /* String-to-Integer conversion */ 85 86 Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer, 87 ACPI_ANY_BASE, &Value); 88 if (ACPI_FAILURE (Status)) 89 { 90 return (Status); 91 } 92 break; 93 94 case ACPI_TYPE_BUFFER: 95 96 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ 97 98 if (OriginalObject->Buffer.Length > 8) 99 { 100 return (AE_AML_OPERAND_TYPE); 101 } 102 103 /* Extract each buffer byte to create the integer */ 104 105 for (i = 0; i < OriginalObject->Buffer.Length; i++) 106 { 107 Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8)); 108 } 109 break; 110 111 default: 112 113 return (AE_AML_OPERAND_TYPE); 114 } 115 116 NewObject = AcpiUtCreateIntegerObject (Value); 117 if (!NewObject) 118 { 119 return (AE_NO_MEMORY); 120 } 121 122 *ReturnObject = NewObject; 123 return (AE_OK); 124 } 125 126 127 /******************************************************************************* 128 * 129 * FUNCTION: AcpiNsConvertToString 130 * 131 * PARAMETERS: OriginalObject - Object to be converted 132 * ReturnObject - Where the new converted object is returned 133 * 134 * RETURN: Status. AE_OK if conversion was successful. 135 * 136 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. 137 * 138 ******************************************************************************/ 139 140 ACPI_STATUS 141 AcpiNsConvertToString ( 142 ACPI_OPERAND_OBJECT *OriginalObject, 143 ACPI_OPERAND_OBJECT **ReturnObject) 144 { 145 ACPI_OPERAND_OBJECT *NewObject; 146 ACPI_SIZE Length; 147 ACPI_STATUS Status; 148 149 150 switch (OriginalObject->Common.Type) 151 { 152 case ACPI_TYPE_INTEGER: 153 /* 154 * Integer-to-String conversion. Commonly, convert 155 * an integer of value 0 to a NULL string. The last element of 156 * _BIF and _BIX packages occasionally need this fix. 157 */ 158 if (OriginalObject->Integer.Value == 0) 159 { 160 /* Allocate a new NULL string object */ 161 162 NewObject = AcpiUtCreateStringObject (0); 163 if (!NewObject) 164 { 165 return (AE_NO_MEMORY); 166 } 167 } 168 else 169 { 170 Status = AcpiExConvertToString (OriginalObject, &NewObject, 171 ACPI_IMPLICIT_CONVERT_HEX); 172 if (ACPI_FAILURE (Status)) 173 { 174 return (Status); 175 } 176 } 177 break; 178 179 case ACPI_TYPE_BUFFER: 180 /* 181 * Buffer-to-String conversion. Use a ToString 182 * conversion, no transform performed on the buffer data. The best 183 * example of this is the _BIF method, where the string data from 184 * the battery is often (incorrectly) returned as buffer object(s). 185 */ 186 Length = 0; 187 while ((Length < OriginalObject->Buffer.Length) && 188 (OriginalObject->Buffer.Pointer[Length])) 189 { 190 Length++; 191 } 192 193 /* Allocate a new string object */ 194 195 NewObject = AcpiUtCreateStringObject (Length); 196 if (!NewObject) 197 { 198 return (AE_NO_MEMORY); 199 } 200 201 /* 202 * Copy the raw buffer data with no transform. String is already NULL 203 * terminated at Length+1. 204 */ 205 ACPI_MEMCPY (NewObject->String.Pointer, 206 OriginalObject->Buffer.Pointer, Length); 207 break; 208 209 default: 210 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 321 return (AE_AML_OPERAND_TYPE); 322 } 323 324 *ReturnObject = NewObject; 325 return (AE_OK); 326 } 327 328 329 /******************************************************************************* 330 * 331 * FUNCTION: AcpiNsConvertToUnicode 332 * 333 * PARAMETERS: OriginalObject - ASCII String Object to be converted 334 * ReturnObject - Where the new converted object is returned 335 * 336 * RETURN: Status. AE_OK if conversion was successful. 337 * 338 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer. 339 * 340 ******************************************************************************/ 341 342 ACPI_STATUS 343 AcpiNsConvertToUnicode ( 344 ACPI_OPERAND_OBJECT *OriginalObject, 345 ACPI_OPERAND_OBJECT **ReturnObject) 346 { 347 ACPI_OPERAND_OBJECT *NewObject; 348 char *AsciiString; 349 UINT16 *UnicodeBuffer; 350 UINT32 UnicodeLength; 351 UINT32 i; 352 353 354 if (!OriginalObject) 355 { 356 return (AE_OK); 357 } 358 359 /* If a Buffer was returned, it must be at least two bytes long */ 360 361 if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER) 362 { 363 if (OriginalObject->Buffer.Length < 2) 364 { 365 return (AE_AML_OPERAND_VALUE); 366 } 367 368 *ReturnObject = NULL; 369 return (AE_OK); 370 } 371 372 /* 373 * The original object is an ASCII string. Convert this string to 374 * a unicode buffer. 375 */ 376 AsciiString = OriginalObject->String.Pointer; 377 UnicodeLength = (OriginalObject->String.Length * 2) + 2; 378 379 /* Create a new buffer object for the Unicode data */ 380 381 NewObject = AcpiUtCreateBufferObject (UnicodeLength); 382 if (!NewObject) 383 { 384 return (AE_NO_MEMORY); 385 } 386 387 UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer); 388 389 /* Convert ASCII to Unicode */ 390 391 for (i = 0; i < OriginalObject->String.Length; i++) 392 { 393 UnicodeBuffer[i] = (UINT16) AsciiString[i]; 394 } 395 396 *ReturnObject = NewObject; 397 return (AE_OK); 398 } 399 400 401 /******************************************************************************* 402 * 403 * FUNCTION: AcpiNsConvertToResource 404 * 405 * PARAMETERS: OriginalObject - Object to be converted 406 * ReturnObject - Where the new converted object is returned 407 * 408 * RETURN: Status. AE_OK if conversion was successful 409 * 410 * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate 411 * Buffer. 412 * 413 ******************************************************************************/ 414 415 ACPI_STATUS 416 AcpiNsConvertToResource ( 417 ACPI_OPERAND_OBJECT *OriginalObject, 418 ACPI_OPERAND_OBJECT **ReturnObject) 419 { 420 ACPI_OPERAND_OBJECT *NewObject; 421 UINT8 *Buffer; 422 423 424 /* 425 * We can fix the following cases for an expected resource template: 426 * 1. No return value (interpreter slack mode is disabled) 427 * 2. A "Return (Zero)" statement 428 * 3. A "Return empty buffer" statement 429 * 430 * We will return a buffer containing a single EndTag 431 * resource descriptor. 432 */ 433 if (OriginalObject) 434 { 435 switch (OriginalObject->Common.Type) 436 { 437 case ACPI_TYPE_INTEGER: 438 439 /* We can only repair an Integer==0 */ 440 441 if (OriginalObject->Integer.Value) 442 { 443 return (AE_AML_OPERAND_TYPE); 444 } 445 break; 446 447 case ACPI_TYPE_BUFFER: 448 449 if (OriginalObject->Buffer.Length) 450 { 451 /* Additional checks can be added in the future */ 452 453 *ReturnObject = NULL; 454 return (AE_OK); 455 } 456 break; 457 458 case ACPI_TYPE_STRING: 459 default: 460 461 return (AE_AML_OPERAND_TYPE); 462 } 463 } 464 465 /* Create the new buffer object for the resource descriptor */ 466 467 NewObject = AcpiUtCreateBufferObject (2); 468 if (!NewObject) 469 { 470 return (AE_NO_MEMORY); 471 } 472 473 Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer); 474 475 /* Initialize the Buffer with a single EndTag descriptor */ 476 477 Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); 478 Buffer[1] = 0x00; 479 480 *ReturnObject = NewObject; 481 return (AE_OK); 482 } 483