1 /******************************************************************************
   2  *
   3  * Module Name: nsconvert - Object conversions for objects returned by
   4  *                          predefined methods
   5  *
   6  *****************************************************************************/
   7 
   8 /*
   9  * Copyright (C) 2000 - 2014, 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 "acpi.h"
  48 #include "accommon.h"
  49 #include "acnamesp.h"
  50 #include "acinterp.h"
  51 #include "acpredef.h"
  52 #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 }