1 /****************************************************************************** 2 * 3 * Module Name: nsconvert - Object conversions for objects returned by 4 * predefined methods 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2020, 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, &Value); 87 if (ACPI_FAILURE (Status)) 88 { 89 return (Status); 90 } 91 break; 92 93 case ACPI_TYPE_BUFFER: 94 95 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ 96 97 if (OriginalObject->Buffer.Length > 8) 98 { 99 return (AE_AML_OPERAND_TYPE); 100 } 101 102 /* Extract each buffer byte to create the integer */ 103 104 for (i = 0; i < OriginalObject->Buffer.Length; i++) 105 { 106 Value |= ((UINT64) 107 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, 171 &NewObject, 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 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 267 (OriginalObject->String.Length); 268 if (!NewObject) 269 { 270 return (AE_NO_MEMORY); 271 } 272 273 memcpy (NewObject->Buffer.Pointer, 274 OriginalObject->String.Pointer, OriginalObject->String.Length); 275 break; 276 277 case ACPI_TYPE_PACKAGE: 278 /* 279 * This case is often seen for predefined names that must return a 280 * Buffer object with multiple DWORD integers within. For example, 281 * _FDE and _GTM. The Package can be converted to a Buffer. 282 */ 283 284 /* All elements of the Package must be integers */ 285 286 Elements = OriginalObject->Package.Elements; 287 Count = OriginalObject->Package.Count; 288 289 for (i = 0; i < Count; i++) 290 { 291 if ((!*Elements) || 292 ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)) 293 { 294 return (AE_AML_OPERAND_TYPE); 295 } 296 Elements++; 297 } 298 299 /* Create the new buffer object to replace the Package */ 300 301 NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count)); 302 if (!NewObject) 303 { 304 return (AE_NO_MEMORY); 305 } 306 307 /* Copy the package elements (integers) to the buffer as DWORDs */ 308 309 Elements = OriginalObject->Package.Elements; 310 DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer); 311 312 for (i = 0; i < Count; i++) 313 { 314 *DwordBuffer = (UINT32) (*Elements)->Integer.Value; 315 DwordBuffer++; 316 Elements++; 317 } 318 break; 319 320 default: 321 322 return (AE_AML_OPERAND_TYPE); 323 } 324 325 *ReturnObject = NewObject; 326 return (AE_OK); 327 } 328 329 330 /******************************************************************************* 331 * 332 * FUNCTION: AcpiNsConvertToUnicode 333 * 334 * PARAMETERS: Scope - Namespace node for the method/object 335 * 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_NAMESPACE_NODE *Scope, 347 ACPI_OPERAND_OBJECT *OriginalObject, 348 ACPI_OPERAND_OBJECT **ReturnObject) 349 { 350 ACPI_OPERAND_OBJECT *NewObject; 351 char *AsciiString; 352 UINT16 *UnicodeBuffer; 353 UINT32 UnicodeLength; 354 UINT32 i; 355 356 357 if (!OriginalObject) 358 { 359 return (AE_OK); 360 } 361 362 /* If a Buffer was returned, it must be at least two bytes long */ 363 364 if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER) 365 { 366 if (OriginalObject->Buffer.Length < 2) 367 { 368 return (AE_AML_OPERAND_VALUE); 369 } 370 371 *ReturnObject = NULL; 372 return (AE_OK); 373 } 374 375 /* 376 * The original object is an ASCII string. Convert this string to 377 * a unicode buffer. 378 */ 379 AsciiString = OriginalObject->String.Pointer; 380 UnicodeLength = (OriginalObject->String.Length * 2) + 2; 381 382 /* Create a new buffer object for the Unicode data */ 383 384 NewObject = AcpiUtCreateBufferObject (UnicodeLength); 385 if (!NewObject) 386 { 387 return (AE_NO_MEMORY); 388 } 389 390 UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer); 391 392 /* Convert ASCII to Unicode */ 393 394 for (i = 0; i < OriginalObject->String.Length; i++) 395 { 396 UnicodeBuffer[i] = (UINT16) AsciiString[i]; 397 } 398 399 *ReturnObject = NewObject; 400 return (AE_OK); 401 } 402 403 404 /******************************************************************************* 405 * 406 * FUNCTION: AcpiNsConvertToResource 407 * 408 * PARAMETERS: Scope - Namespace node for the method/object 409 * OriginalObject - Object to be converted 410 * ReturnObject - Where the new converted object is returned 411 * 412 * RETURN: Status. AE_OK if conversion was successful 413 * 414 * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate 415 * Buffer. 416 * 417 ******************************************************************************/ 418 419 ACPI_STATUS 420 AcpiNsConvertToResource ( 421 ACPI_NAMESPACE_NODE *Scope, 422 ACPI_OPERAND_OBJECT *OriginalObject, 423 ACPI_OPERAND_OBJECT **ReturnObject) 424 { 425 ACPI_OPERAND_OBJECT *NewObject; 426 UINT8 *Buffer; 427 428 429 /* 430 * We can fix the following cases for an expected resource template: 431 * 1. No return value (interpreter slack mode is disabled) 432 * 2. A "Return (Zero)" statement 433 * 3. A "Return empty buffer" statement 434 * 435 * We will return a buffer containing a single EndTag 436 * resource descriptor. 437 */ 438 if (OriginalObject) 439 { 440 switch (OriginalObject->Common.Type) 441 { 442 case ACPI_TYPE_INTEGER: 443 444 /* We can only repair an Integer==0 */ 445 446 if (OriginalObject->Integer.Value) 447 { 448 return (AE_AML_OPERAND_TYPE); 449 } 450 break; 451 452 case ACPI_TYPE_BUFFER: 453 454 if (OriginalObject->Buffer.Length) 455 { 456 /* Additional checks can be added in the future */ 457 458 *ReturnObject = NULL; 459 return (AE_OK); 460 } 461 break; 462 463 case ACPI_TYPE_STRING: 464 default: 465 466 return (AE_AML_OPERAND_TYPE); 467 } 468 } 469 470 /* Create the new buffer object for the resource descriptor */ 471 472 NewObject = AcpiUtCreateBufferObject (2); 473 if (!NewObject) 474 { 475 return (AE_NO_MEMORY); 476 } 477 478 Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer); 479 480 /* Initialize the Buffer with a single EndTag descriptor */ 481 482 Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); 483 Buffer[1] = 0x00; 484 485 *ReturnObject = NewObject; 486 return (AE_OK); 487 } 488 489 490 /******************************************************************************* 491 * 492 * FUNCTION: AcpiNsConvertToReference 493 * 494 * PARAMETERS: Scope - Namespace node for the method/object 495 * OriginalObject - Object to be converted 496 * ReturnObject - Where the new converted object is returned 497 * 498 * RETURN: Status. AE_OK if conversion was successful 499 * 500 * DESCRIPTION: Attempt to convert a Integer object to a ObjectReference. 501 * Buffer. 502 * 503 ******************************************************************************/ 504 505 ACPI_STATUS 506 AcpiNsConvertToReference ( 507 ACPI_NAMESPACE_NODE *Scope, 508 ACPI_OPERAND_OBJECT *OriginalObject, 509 ACPI_OPERAND_OBJECT **ReturnObject) 510 { 511 ACPI_OPERAND_OBJECT *NewObject = NULL; 512 ACPI_STATUS Status; 513 ACPI_NAMESPACE_NODE *Node; 514 ACPI_GENERIC_STATE ScopeInfo; 515 char *Name; 516 517 518 ACPI_FUNCTION_NAME (NsConvertToReference); 519 520 521 /* Convert path into internal presentation */ 522 523 Status = AcpiNsInternalizeName (OriginalObject->String.Pointer, &Name); 524 if (ACPI_FAILURE (Status)) 525 { 526 return_ACPI_STATUS (Status); 527 } 528 529 /* Find the namespace node */ 530 531 ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Scope); 532 Status = AcpiNsLookup (&ScopeInfo, Name, 533 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 534 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); 535 if (ACPI_FAILURE (Status)) 536 { 537 /* Check if we are resolving a named reference within a package */ 538 539 ACPI_ERROR_NAMESPACE (&ScopeInfo, 540 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 (Status); 566 } 567