1 /****************************************************************************** 2 * 3 * Module Name: nsconvert - Object conversions for objects returned by 4 * predefined methods 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2016, 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.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 * 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, AcpiGbl_IntegerByteWidth, &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) 108 OriginalObject->Buffer.Pointer[i] << (i * 8)); 109 } 110 break; 111 112 default: 113 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, 172 &NewObject, 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 memcpy (NewObject->String.Pointer, 207 OriginalObject->Buffer.Pointer, Length); 208 break; 209 210 default: 211 212 return (AE_AML_OPERAND_TYPE); 213 } 214 215 *ReturnObject = NewObject; 216 return (AE_OK); 217 } 218 219 220 /******************************************************************************* 221 * 222 * FUNCTION: AcpiNsConvertToBuffer 223 * 224 * PARAMETERS: OriginalObject - Object to be converted 225 * ReturnObject - Where the new converted object is returned 226 * 227 * RETURN: Status. AE_OK if conversion was successful. 228 * 229 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. 230 * 231 ******************************************************************************/ 232 233 ACPI_STATUS 234 AcpiNsConvertToBuffer ( 235 ACPI_OPERAND_OBJECT *OriginalObject, 236 ACPI_OPERAND_OBJECT **ReturnObject) 237 { 238 ACPI_OPERAND_OBJECT *NewObject; 239 ACPI_STATUS Status; 240 ACPI_OPERAND_OBJECT **Elements; 241 UINT32 *DwordBuffer; 242 UINT32 Count; 243 UINT32 i; 244 245 246 switch (OriginalObject->Common.Type) 247 { 248 case ACPI_TYPE_INTEGER: 249 /* 250 * Integer-to-Buffer conversion. 251 * Convert the Integer to a packed-byte buffer. _MAT and other 252 * objects need this sometimes, if a read has been performed on a 253 * Field object that is less than or equal to the global integer 254 * size (32 or 64 bits). 255 */ 256 Status = AcpiExConvertToBuffer (OriginalObject, &NewObject); 257 if (ACPI_FAILURE (Status)) 258 { 259 return (Status); 260 } 261 break; 262 263 case ACPI_TYPE_STRING: 264 265 /* String-to-Buffer conversion. Simple data copy */ 266 267 NewObject = AcpiUtCreateBufferObject 268 (OriginalObject->String.Length); 269 if (!NewObject) 270 { 271 return (AE_NO_MEMORY); 272 } 273 274 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: Scope - Namespace node for the method/object 336 * OriginalObject - ASCII String Object to be converted 337 * ReturnObject - Where the new converted object is returned 338 * 339 * RETURN: Status. AE_OK if conversion was successful. 340 * 341 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer. 342 * 343 ******************************************************************************/ 344 345 ACPI_STATUS 346 AcpiNsConvertToUnicode ( 347 ACPI_NAMESPACE_NODE *Scope, 348 ACPI_OPERAND_OBJECT *OriginalObject, 349 ACPI_OPERAND_OBJECT **ReturnObject) 350 { 351 ACPI_OPERAND_OBJECT *NewObject; 352 char *AsciiString; 353 UINT16 *UnicodeBuffer; 354 UINT32 UnicodeLength; 355 UINT32 i; 356 357 358 if (!OriginalObject) 359 { 360 return (AE_OK); 361 } 362 363 /* If a Buffer was returned, it must be at least two bytes long */ 364 365 if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER) 366 { 367 if (OriginalObject->Buffer.Length < 2) 368 { 369 return (AE_AML_OPERAND_VALUE); 370 } 371 372 *ReturnObject = NULL; 373 return (AE_OK); 374 } 375 376 /* 377 * The original object is an ASCII string. Convert this string to 378 * a unicode buffer. 379 */ 380 AsciiString = OriginalObject->String.Pointer; 381 UnicodeLength = (OriginalObject->String.Length * 2) + 2; 382 383 /* Create a new buffer object for the Unicode data */ 384 385 NewObject = AcpiUtCreateBufferObject (UnicodeLength); 386 if (!NewObject) 387 { 388 return (AE_NO_MEMORY); 389 } 390 391 UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer); 392 393 /* Convert ASCII to Unicode */ 394 395 for (i = 0; i < OriginalObject->String.Length; i++) 396 { 397 UnicodeBuffer[i] = (UINT16) AsciiString[i]; 398 } 399 400 *ReturnObject = NewObject; 401 return (AE_OK); 402 } 403 404 405 /******************************************************************************* 406 * 407 * FUNCTION: AcpiNsConvertToResource 408 * 409 * PARAMETERS: Scope - Namespace node for the method/object 410 * OriginalObject - Object to be converted 411 * ReturnObject - Where the new converted object is returned 412 * 413 * RETURN: Status. AE_OK if conversion was successful 414 * 415 * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate 416 * Buffer. 417 * 418 ******************************************************************************/ 419 420 ACPI_STATUS 421 AcpiNsConvertToResource ( 422 ACPI_NAMESPACE_NODE *Scope, 423 ACPI_OPERAND_OBJECT *OriginalObject, 424 ACPI_OPERAND_OBJECT **ReturnObject) 425 { 426 ACPI_OPERAND_OBJECT *NewObject; 427 UINT8 *Buffer; 428 429 430 /* 431 * We can fix the following cases for an expected resource template: 432 * 1. No return value (interpreter slack mode is disabled) 433 * 2. A "Return (Zero)" statement 434 * 3. A "Return empty buffer" statement 435 * 436 * We will return a buffer containing a single EndTag 437 * resource descriptor. 438 */ 439 if (OriginalObject) 440 { 441 switch (OriginalObject->Common.Type) 442 { 443 case ACPI_TYPE_INTEGER: 444 445 /* We can only repair an Integer==0 */ 446 447 if (OriginalObject->Integer.Value) 448 { 449 return (AE_AML_OPERAND_TYPE); 450 } 451 break; 452 453 case ACPI_TYPE_BUFFER: 454 455 if (OriginalObject->Buffer.Length) 456 { 457 /* Additional checks can be added in the future */ 458 459 *ReturnObject = NULL; 460 return (AE_OK); 461 } 462 break; 463 464 case ACPI_TYPE_STRING: 465 default: 466 467 return (AE_AML_OPERAND_TYPE); 468 } 469 } 470 471 /* Create the new buffer object for the resource descriptor */ 472 473 NewObject = AcpiUtCreateBufferObject (2); 474 if (!NewObject) 475 { 476 return (AE_NO_MEMORY); 477 } 478 479 Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer); 480 481 /* Initialize the Buffer with a single EndTag descriptor */ 482 483 Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); 484 Buffer[1] = 0x00; 485 486 *ReturnObject = NewObject; 487 return (AE_OK); 488 } 489 490 491 /******************************************************************************* 492 * 493 * FUNCTION: AcpiNsConvertToReference 494 * 495 * PARAMETERS: Scope - Namespace node for the method/object 496 * OriginalObject - Object to be converted 497 * ReturnObject - Where the new converted object is returned 498 * 499 * RETURN: Status. AE_OK if conversion was successful 500 * 501 * DESCRIPTION: Attempt to convert a Integer object to a ObjectReference. 502 * Buffer. 503 * 504 ******************************************************************************/ 505 506 ACPI_STATUS 507 AcpiNsConvertToReference ( 508 ACPI_NAMESPACE_NODE *Scope, 509 ACPI_OPERAND_OBJECT *OriginalObject, 510 ACPI_OPERAND_OBJECT **ReturnObject) 511 { 512 ACPI_OPERAND_OBJECT *NewObject = NULL; 513 ACPI_STATUS Status; 514 ACPI_NAMESPACE_NODE *Node; 515 ACPI_GENERIC_STATE ScopeInfo; 516 char *Name; 517 518 519 ACPI_FUNCTION_NAME (NsConvertToReference); 520 521 522 /* Convert path into internal presentation */ 523 524 Status = AcpiNsInternalizeName (OriginalObject->String.Pointer, &Name); 525 if (ACPI_FAILURE (Status)) 526 { 527 return_ACPI_STATUS (Status); 528 } 529 530 /* Find the namespace node */ 531 532 ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Scope); 533 Status = AcpiNsLookup (&ScopeInfo, Name, 534 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 535 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); 536 if (ACPI_FAILURE (Status)) 537 { 538 /* Check if we are resolving a named reference within a package */ 539 540 ACPI_ERROR_NAMESPACE (OriginalObject->String.Pointer, Status); 541 goto ErrorExit; 542 } 543 544 /* Create and init a new internal ACPI object */ 545 546 NewObject = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); 547 if (!NewObject) 548 { 549 Status = AE_NO_MEMORY; 550 goto ErrorExit; 551 } 552 NewObject->Reference.Node = Node; 553 NewObject->Reference.Object = Node->Object; 554 NewObject->Reference.Class = ACPI_REFCLASS_NAME; 555 556 /* 557 * Increase reference of the object if needed (the object is likely a 558 * null for device nodes). 559 */ 560 AcpiUtAddReference (Node->Object); 561 562 ErrorExit: 563 ACPI_FREE (Name); 564 *ReturnObject = NewObject; 565 return (AE_OK); 566 } 567