linux/drivers/acpi/acpica/nsconvert.c
<<
>>
Prefs
   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#include <acpi/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
  53ACPI_MODULE_NAME("nsconvert")
  54
  55/*******************************************************************************
  56 *
  57 * FUNCTION:    acpi_ns_convert_to_integer
  58 *
  59 * PARAMETERS:  original_object     - Object to be converted
  60 *              return_object       - Where the new converted object is returned
  61 *
  62 * RETURN:      Status. AE_OK if conversion was successful.
  63 *
  64 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
  65 *
  66 ******************************************************************************/
  67acpi_status
  68acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
  69                           union acpi_operand_object **return_object)
  70{
  71        union acpi_operand_object *new_object;
  72        acpi_status status;
  73        u64 value = 0;
  74        u32 i;
  75
  76        switch (original_object->common.type) {
  77        case ACPI_TYPE_STRING:
  78
  79                /* String-to-Integer conversion */
  80
  81                status = acpi_ut_strtoul64(original_object->string.pointer,
  82                                           acpi_gbl_integer_byte_width, &value);
  83                if (ACPI_FAILURE(status)) {
  84                        return (status);
  85                }
  86                break;
  87
  88        case ACPI_TYPE_BUFFER:
  89
  90                /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
  91
  92                if (original_object->buffer.length > 8) {
  93                        return (AE_AML_OPERAND_TYPE);
  94                }
  95
  96                /* Extract each buffer byte to create the integer */
  97
  98                for (i = 0; i < original_object->buffer.length; i++) {
  99                        value |=
 100                            ((u64)original_object->buffer.
 101                             pointer[i] << (i * 8));
 102                }
 103                break;
 104
 105        default:
 106
 107                return (AE_AML_OPERAND_TYPE);
 108        }
 109
 110        new_object = acpi_ut_create_integer_object(value);
 111        if (!new_object) {
 112                return (AE_NO_MEMORY);
 113        }
 114
 115        *return_object = new_object;
 116        return (AE_OK);
 117}
 118
 119/*******************************************************************************
 120 *
 121 * FUNCTION:    acpi_ns_convert_to_string
 122 *
 123 * PARAMETERS:  original_object     - Object to be converted
 124 *              return_object       - Where the new converted object is returned
 125 *
 126 * RETURN:      Status. AE_OK if conversion was successful.
 127 *
 128 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
 129 *
 130 ******************************************************************************/
 131
 132acpi_status
 133acpi_ns_convert_to_string(union acpi_operand_object *original_object,
 134                          union acpi_operand_object **return_object)
 135{
 136        union acpi_operand_object *new_object;
 137        acpi_size length;
 138        acpi_status status;
 139
 140        switch (original_object->common.type) {
 141        case ACPI_TYPE_INTEGER:
 142                /*
 143                 * Integer-to-String conversion. Commonly, convert
 144                 * an integer of value 0 to a NULL string. The last element of
 145                 * _BIF and _BIX packages occasionally need this fix.
 146                 */
 147                if (original_object->integer.value == 0) {
 148
 149                        /* Allocate a new NULL string object */
 150
 151                        new_object = acpi_ut_create_string_object(0);
 152                        if (!new_object) {
 153                                return (AE_NO_MEMORY);
 154                        }
 155                } else {
 156                        status =
 157                            acpi_ex_convert_to_string(original_object,
 158                                                      &new_object,
 159                                                      ACPI_IMPLICIT_CONVERT_HEX);
 160                        if (ACPI_FAILURE(status)) {
 161                                return (status);
 162                        }
 163                }
 164                break;
 165
 166        case ACPI_TYPE_BUFFER:
 167                /*
 168                 * Buffer-to-String conversion. Use a to_string
 169                 * conversion, no transform performed on the buffer data. The best
 170                 * example of this is the _BIF method, where the string data from
 171                 * the battery is often (incorrectly) returned as buffer object(s).
 172                 */
 173                length = 0;
 174                while ((length < original_object->buffer.length) &&
 175                       (original_object->buffer.pointer[length])) {
 176                        length++;
 177                }
 178
 179                /* Allocate a new string object */
 180
 181                new_object = acpi_ut_create_string_object(length);
 182                if (!new_object) {
 183                        return (AE_NO_MEMORY);
 184                }
 185
 186                /*
 187                 * Copy the raw buffer data with no transform. String is already NULL
 188                 * terminated at Length+1.
 189                 */
 190                memcpy(new_object->string.pointer,
 191                       original_object->buffer.pointer, length);
 192                break;
 193
 194        default:
 195
 196                return (AE_AML_OPERAND_TYPE);
 197        }
 198
 199        *return_object = new_object;
 200        return (AE_OK);
 201}
 202
 203/*******************************************************************************
 204 *
 205 * FUNCTION:    acpi_ns_convert_to_buffer
 206 *
 207 * PARAMETERS:  original_object     - Object to be converted
 208 *              return_object       - Where the new converted object is returned
 209 *
 210 * RETURN:      Status. AE_OK if conversion was successful.
 211 *
 212 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
 213 *
 214 ******************************************************************************/
 215
 216acpi_status
 217acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
 218                          union acpi_operand_object **return_object)
 219{
 220        union acpi_operand_object *new_object;
 221        acpi_status status;
 222        union acpi_operand_object **elements;
 223        u32 *dword_buffer;
 224        u32 count;
 225        u32 i;
 226
 227        switch (original_object->common.type) {
 228        case ACPI_TYPE_INTEGER:
 229                /*
 230                 * Integer-to-Buffer conversion.
 231                 * Convert the Integer to a packed-byte buffer. _MAT and other
 232                 * objects need this sometimes, if a read has been performed on a
 233                 * Field object that is less than or equal to the global integer
 234                 * size (32 or 64 bits).
 235                 */
 236                status =
 237                    acpi_ex_convert_to_buffer(original_object, &new_object);
 238                if (ACPI_FAILURE(status)) {
 239                        return (status);
 240                }
 241                break;
 242
 243        case ACPI_TYPE_STRING:
 244
 245                /* String-to-Buffer conversion. Simple data copy */
 246
 247                new_object =
 248                    acpi_ut_create_buffer_object(original_object->string.
 249                                                 length);
 250                if (!new_object) {
 251                        return (AE_NO_MEMORY);
 252                }
 253
 254                memcpy(new_object->buffer.pointer,
 255                       original_object->string.pointer,
 256                       original_object->string.length);
 257                break;
 258
 259        case ACPI_TYPE_PACKAGE:
 260                /*
 261                 * This case is often seen for predefined names that must return a
 262                 * Buffer object with multiple DWORD integers within. For example,
 263                 * _FDE and _GTM. The Package can be converted to a Buffer.
 264                 */
 265
 266                /* All elements of the Package must be integers */
 267
 268                elements = original_object->package.elements;
 269                count = original_object->package.count;
 270
 271                for (i = 0; i < count; i++) {
 272                        if ((!*elements) ||
 273                            ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
 274                                return (AE_AML_OPERAND_TYPE);
 275                        }
 276                        elements++;
 277                }
 278
 279                /* Create the new buffer object to replace the Package */
 280
 281                new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
 282                if (!new_object) {
 283                        return (AE_NO_MEMORY);
 284                }
 285
 286                /* Copy the package elements (integers) to the buffer as DWORDs */
 287
 288                elements = original_object->package.elements;
 289                dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
 290
 291                for (i = 0; i < count; i++) {
 292                        *dword_buffer = (u32)(*elements)->integer.value;
 293                        dword_buffer++;
 294                        elements++;
 295                }
 296                break;
 297
 298        default:
 299
 300                return (AE_AML_OPERAND_TYPE);
 301        }
 302
 303        *return_object = new_object;
 304        return (AE_OK);
 305}
 306
 307/*******************************************************************************
 308 *
 309 * FUNCTION:    acpi_ns_convert_to_unicode
 310 *
 311 * PARAMETERS:  original_object     - ASCII String Object to be converted
 312 *              return_object       - Where the new converted object is returned
 313 *
 314 * RETURN:      Status. AE_OK if conversion was successful.
 315 *
 316 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
 317 *
 318 ******************************************************************************/
 319
 320acpi_status
 321acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
 322                           union acpi_operand_object **return_object)
 323{
 324        union acpi_operand_object *new_object;
 325        char *ascii_string;
 326        u16 *unicode_buffer;
 327        u32 unicode_length;
 328        u32 i;
 329
 330        if (!original_object) {
 331                return (AE_OK);
 332        }
 333
 334        /* If a Buffer was returned, it must be at least two bytes long */
 335
 336        if (original_object->common.type == ACPI_TYPE_BUFFER) {
 337                if (original_object->buffer.length < 2) {
 338                        return (AE_AML_OPERAND_VALUE);
 339                }
 340
 341                *return_object = NULL;
 342                return (AE_OK);
 343        }
 344
 345        /*
 346         * The original object is an ASCII string. Convert this string to
 347         * a unicode buffer.
 348         */
 349        ascii_string = original_object->string.pointer;
 350        unicode_length = (original_object->string.length * 2) + 2;
 351
 352        /* Create a new buffer object for the Unicode data */
 353
 354        new_object = acpi_ut_create_buffer_object(unicode_length);
 355        if (!new_object) {
 356                return (AE_NO_MEMORY);
 357        }
 358
 359        unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
 360
 361        /* Convert ASCII to Unicode */
 362
 363        for (i = 0; i < original_object->string.length; i++) {
 364                unicode_buffer[i] = (u16)ascii_string[i];
 365        }
 366
 367        *return_object = new_object;
 368        return (AE_OK);
 369}
 370
 371/*******************************************************************************
 372 *
 373 * FUNCTION:    acpi_ns_convert_to_resource
 374 *
 375 * PARAMETERS:  original_object     - Object to be converted
 376 *              return_object       - Where the new converted object is returned
 377 *
 378 * RETURN:      Status. AE_OK if conversion was successful
 379 *
 380 * DESCRIPTION: Attempt to convert a Integer object to a resource_template
 381 *              Buffer.
 382 *
 383 ******************************************************************************/
 384
 385acpi_status
 386acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
 387                            union acpi_operand_object **return_object)
 388{
 389        union acpi_operand_object *new_object;
 390        u8 *buffer;
 391
 392        /*
 393         * We can fix the following cases for an expected resource template:
 394         * 1. No return value (interpreter slack mode is disabled)
 395         * 2. A "Return (Zero)" statement
 396         * 3. A "Return empty buffer" statement
 397         *
 398         * We will return a buffer containing a single end_tag
 399         * resource descriptor.
 400         */
 401        if (original_object) {
 402                switch (original_object->common.type) {
 403                case ACPI_TYPE_INTEGER:
 404
 405                        /* We can only repair an Integer==0 */
 406
 407                        if (original_object->integer.value) {
 408                                return (AE_AML_OPERAND_TYPE);
 409                        }
 410                        break;
 411
 412                case ACPI_TYPE_BUFFER:
 413
 414                        if (original_object->buffer.length) {
 415
 416                                /* Additional checks can be added in the future */
 417
 418                                *return_object = NULL;
 419                                return (AE_OK);
 420                        }
 421                        break;
 422
 423                case ACPI_TYPE_STRING:
 424                default:
 425
 426                        return (AE_AML_OPERAND_TYPE);
 427                }
 428        }
 429
 430        /* Create the new buffer object for the resource descriptor */
 431
 432        new_object = acpi_ut_create_buffer_object(2);
 433        if (!new_object) {
 434                return (AE_NO_MEMORY);
 435        }
 436
 437        buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
 438
 439        /* Initialize the Buffer with a single end_tag descriptor */
 440
 441        buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
 442        buffer[1] = 0x00;
 443
 444        *return_object = new_object;
 445        return (AE_OK);
 446}
 447