root/drivers/acpi/acpica/nsconvert.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ns_convert_to_string
  3. acpi_ns_convert_to_buffer
  4. acpi_ns_convert_to_unicode
  5. acpi_ns_convert_to_resource
  6. acpi_ns_convert_to_reference

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Module Name: nsconvert - Object conversions for objects returned by
   5  *                          predefined methods
   6  *
   7  * Copyright (C) 2000 - 2019, Intel Corp.
   8  *
   9  *****************************************************************************/
  10 
  11 #include <acpi/acpi.h>
  12 #include "accommon.h"
  13 #include "acnamesp.h"
  14 #include "acinterp.h"
  15 #include "acpredef.h"
  16 #include "amlresrc.h"
  17 
  18 #define _COMPONENT          ACPI_NAMESPACE
  19 ACPI_MODULE_NAME("nsconvert")
  20 
  21 /*******************************************************************************
  22  *
  23  * FUNCTION:    acpi_ns_convert_to_integer
  24  *
  25  * PARAMETERS:  original_object     - Object to be converted
  26  *              return_object       - Where the new converted object is returned
  27  *
  28  * RETURN:      Status. AE_OK if conversion was successful.
  29  *
  30  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
  31  *
  32  ******************************************************************************/
  33 acpi_status
  34 acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
  35                            union acpi_operand_object **return_object)
  36 {
  37         union acpi_operand_object *new_object;
  38         acpi_status status;
  39         u64 value = 0;
  40         u32 i;
  41 
  42         switch (original_object->common.type) {
  43         case ACPI_TYPE_STRING:
  44 
  45                 /* String-to-Integer conversion */
  46 
  47                 status =
  48                     acpi_ut_strtoul64(original_object->string.pointer, &value);
  49                 if (ACPI_FAILURE(status)) {
  50                         return (status);
  51                 }
  52                 break;
  53 
  54         case ACPI_TYPE_BUFFER:
  55 
  56                 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
  57 
  58                 if (original_object->buffer.length > 8) {
  59                         return (AE_AML_OPERAND_TYPE);
  60                 }
  61 
  62                 /* Extract each buffer byte to create the integer */
  63 
  64                 for (i = 0; i < original_object->buffer.length; i++) {
  65                         value |= ((u64)
  66                                   original_object->buffer.pointer[i] << (i *
  67                                                                          8));
  68                 }
  69                 break;
  70 
  71         default:
  72 
  73                 return (AE_AML_OPERAND_TYPE);
  74         }
  75 
  76         new_object = acpi_ut_create_integer_object(value);
  77         if (!new_object) {
  78                 return (AE_NO_MEMORY);
  79         }
  80 
  81         *return_object = new_object;
  82         return (AE_OK);
  83 }
  84 
  85 /*******************************************************************************
  86  *
  87  * FUNCTION:    acpi_ns_convert_to_string
  88  *
  89  * PARAMETERS:  original_object     - Object to be converted
  90  *              return_object       - Where the new converted object is returned
  91  *
  92  * RETURN:      Status. AE_OK if conversion was successful.
  93  *
  94  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
  95  *
  96  ******************************************************************************/
  97 
  98 acpi_status
  99 acpi_ns_convert_to_string(union acpi_operand_object *original_object,
 100                           union acpi_operand_object **return_object)
 101 {
 102         union acpi_operand_object *new_object;
 103         acpi_size length;
 104         acpi_status status;
 105 
 106         switch (original_object->common.type) {
 107         case ACPI_TYPE_INTEGER:
 108                 /*
 109                  * Integer-to-String conversion. Commonly, convert
 110                  * an integer of value 0 to a NULL string. The last element of
 111                  * _BIF and _BIX packages occasionally need this fix.
 112                  */
 113                 if (original_object->integer.value == 0) {
 114 
 115                         /* Allocate a new NULL string object */
 116 
 117                         new_object = acpi_ut_create_string_object(0);
 118                         if (!new_object) {
 119                                 return (AE_NO_MEMORY);
 120                         }
 121                 } else {
 122                         status = acpi_ex_convert_to_string(original_object,
 123                                                            &new_object,
 124                                                            ACPI_IMPLICIT_CONVERT_HEX);
 125                         if (ACPI_FAILURE(status)) {
 126                                 return (status);
 127                         }
 128                 }
 129                 break;
 130 
 131         case ACPI_TYPE_BUFFER:
 132                 /*
 133                  * Buffer-to-String conversion. Use a to_string
 134                  * conversion, no transform performed on the buffer data. The best
 135                  * example of this is the _BIF method, where the string data from
 136                  * the battery is often (incorrectly) returned as buffer object(s).
 137                  */
 138                 length = 0;
 139                 while ((length < original_object->buffer.length) &&
 140                        (original_object->buffer.pointer[length])) {
 141                         length++;
 142                 }
 143 
 144                 /* Allocate a new string object */
 145 
 146                 new_object = acpi_ut_create_string_object(length);
 147                 if (!new_object) {
 148                         return (AE_NO_MEMORY);
 149                 }
 150 
 151                 /*
 152                  * Copy the raw buffer data with no transform. String is already NULL
 153                  * terminated at Length+1.
 154                  */
 155                 memcpy(new_object->string.pointer,
 156                        original_object->buffer.pointer, length);
 157                 break;
 158 
 159         default:
 160 
 161                 return (AE_AML_OPERAND_TYPE);
 162         }
 163 
 164         *return_object = new_object;
 165         return (AE_OK);
 166 }
 167 
 168 /*******************************************************************************
 169  *
 170  * FUNCTION:    acpi_ns_convert_to_buffer
 171  *
 172  * PARAMETERS:  original_object     - Object to be converted
 173  *              return_object       - Where the new converted object is returned
 174  *
 175  * RETURN:      Status. AE_OK if conversion was successful.
 176  *
 177  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
 178  *
 179  ******************************************************************************/
 180 
 181 acpi_status
 182 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
 183                           union acpi_operand_object **return_object)
 184 {
 185         union acpi_operand_object *new_object;
 186         acpi_status status;
 187         union acpi_operand_object **elements;
 188         u32 *dword_buffer;
 189         u32 count;
 190         u32 i;
 191 
 192         switch (original_object->common.type) {
 193         case ACPI_TYPE_INTEGER:
 194                 /*
 195                  * Integer-to-Buffer conversion.
 196                  * Convert the Integer to a packed-byte buffer. _MAT and other
 197                  * objects need this sometimes, if a read has been performed on a
 198                  * Field object that is less than or equal to the global integer
 199                  * size (32 or 64 bits).
 200                  */
 201                 status =
 202                     acpi_ex_convert_to_buffer(original_object, &new_object);
 203                 if (ACPI_FAILURE(status)) {
 204                         return (status);
 205                 }
 206                 break;
 207 
 208         case ACPI_TYPE_STRING:
 209 
 210                 /* String-to-Buffer conversion. Simple data copy */
 211 
 212                 new_object = acpi_ut_create_buffer_object
 213                     (original_object->string.length);
 214                 if (!new_object) {
 215                         return (AE_NO_MEMORY);
 216                 }
 217 
 218                 memcpy(new_object->buffer.pointer,
 219                        original_object->string.pointer,
 220                        original_object->string.length);
 221                 break;
 222 
 223         case ACPI_TYPE_PACKAGE:
 224                 /*
 225                  * This case is often seen for predefined names that must return a
 226                  * Buffer object with multiple DWORD integers within. For example,
 227                  * _FDE and _GTM. The Package can be converted to a Buffer.
 228                  */
 229 
 230                 /* All elements of the Package must be integers */
 231 
 232                 elements = original_object->package.elements;
 233                 count = original_object->package.count;
 234 
 235                 for (i = 0; i < count; i++) {
 236                         if ((!*elements) ||
 237                             ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
 238                                 return (AE_AML_OPERAND_TYPE);
 239                         }
 240                         elements++;
 241                 }
 242 
 243                 /* Create the new buffer object to replace the Package */
 244 
 245                 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
 246                 if (!new_object) {
 247                         return (AE_NO_MEMORY);
 248                 }
 249 
 250                 /* Copy the package elements (integers) to the buffer as DWORDs */
 251 
 252                 elements = original_object->package.elements;
 253                 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
 254 
 255                 for (i = 0; i < count; i++) {
 256                         *dword_buffer = (u32)(*elements)->integer.value;
 257                         dword_buffer++;
 258                         elements++;
 259                 }
 260                 break;
 261 
 262         default:
 263 
 264                 return (AE_AML_OPERAND_TYPE);
 265         }
 266 
 267         *return_object = new_object;
 268         return (AE_OK);
 269 }
 270 
 271 /*******************************************************************************
 272  *
 273  * FUNCTION:    acpi_ns_convert_to_unicode
 274  *
 275  * PARAMETERS:  scope               - Namespace node for the method/object
 276  *              original_object     - ASCII String Object to be converted
 277  *              return_object       - Where the new converted object is returned
 278  *
 279  * RETURN:      Status. AE_OK if conversion was successful.
 280  *
 281  * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
 282  *
 283  ******************************************************************************/
 284 
 285 acpi_status
 286 acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope,
 287                            union acpi_operand_object *original_object,
 288                            union acpi_operand_object **return_object)
 289 {
 290         union acpi_operand_object *new_object;
 291         char *ascii_string;
 292         u16 *unicode_buffer;
 293         u32 unicode_length;
 294         u32 i;
 295 
 296         if (!original_object) {
 297                 return (AE_OK);
 298         }
 299 
 300         /* If a Buffer was returned, it must be at least two bytes long */
 301 
 302         if (original_object->common.type == ACPI_TYPE_BUFFER) {
 303                 if (original_object->buffer.length < 2) {
 304                         return (AE_AML_OPERAND_VALUE);
 305                 }
 306 
 307                 *return_object = NULL;
 308                 return (AE_OK);
 309         }
 310 
 311         /*
 312          * The original object is an ASCII string. Convert this string to
 313          * a unicode buffer.
 314          */
 315         ascii_string = original_object->string.pointer;
 316         unicode_length = (original_object->string.length * 2) + 2;
 317 
 318         /* Create a new buffer object for the Unicode data */
 319 
 320         new_object = acpi_ut_create_buffer_object(unicode_length);
 321         if (!new_object) {
 322                 return (AE_NO_MEMORY);
 323         }
 324 
 325         unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
 326 
 327         /* Convert ASCII to Unicode */
 328 
 329         for (i = 0; i < original_object->string.length; i++) {
 330                 unicode_buffer[i] = (u16)ascii_string[i];
 331         }
 332 
 333         *return_object = new_object;
 334         return (AE_OK);
 335 }
 336 
 337 /*******************************************************************************
 338  *
 339  * FUNCTION:    acpi_ns_convert_to_resource
 340  *
 341  * PARAMETERS:  scope               - Namespace node for the method/object
 342  *              original_object     - Object to be converted
 343  *              return_object       - Where the new converted object is returned
 344  *
 345  * RETURN:      Status. AE_OK if conversion was successful
 346  *
 347  * DESCRIPTION: Attempt to convert a Integer object to a resource_template
 348  *              Buffer.
 349  *
 350  ******************************************************************************/
 351 
 352 acpi_status
 353 acpi_ns_convert_to_resource(struct acpi_namespace_node *scope,
 354                             union acpi_operand_object *original_object,
 355                             union acpi_operand_object **return_object)
 356 {
 357         union acpi_operand_object *new_object;
 358         u8 *buffer;
 359 
 360         /*
 361          * We can fix the following cases for an expected resource template:
 362          * 1. No return value (interpreter slack mode is disabled)
 363          * 2. A "Return (Zero)" statement
 364          * 3. A "Return empty buffer" statement
 365          *
 366          * We will return a buffer containing a single end_tag
 367          * resource descriptor.
 368          */
 369         if (original_object) {
 370                 switch (original_object->common.type) {
 371                 case ACPI_TYPE_INTEGER:
 372 
 373                         /* We can only repair an Integer==0 */
 374 
 375                         if (original_object->integer.value) {
 376                                 return (AE_AML_OPERAND_TYPE);
 377                         }
 378                         break;
 379 
 380                 case ACPI_TYPE_BUFFER:
 381 
 382                         if (original_object->buffer.length) {
 383 
 384                                 /* Additional checks can be added in the future */
 385 
 386                                 *return_object = NULL;
 387                                 return (AE_OK);
 388                         }
 389                         break;
 390 
 391                 case ACPI_TYPE_STRING:
 392                 default:
 393 
 394                         return (AE_AML_OPERAND_TYPE);
 395                 }
 396         }
 397 
 398         /* Create the new buffer object for the resource descriptor */
 399 
 400         new_object = acpi_ut_create_buffer_object(2);
 401         if (!new_object) {
 402                 return (AE_NO_MEMORY);
 403         }
 404 
 405         buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
 406 
 407         /* Initialize the Buffer with a single end_tag descriptor */
 408 
 409         buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
 410         buffer[1] = 0x00;
 411 
 412         *return_object = new_object;
 413         return (AE_OK);
 414 }
 415 
 416 /*******************************************************************************
 417  *
 418  * FUNCTION:    acpi_ns_convert_to_reference
 419  *
 420  * PARAMETERS:  scope               - Namespace node for the method/object
 421  *              original_object     - Object to be converted
 422  *              return_object       - Where the new converted object is returned
 423  *
 424  * RETURN:      Status. AE_OK if conversion was successful
 425  *
 426  * DESCRIPTION: Attempt to convert a Integer object to a object_reference.
 427  *              Buffer.
 428  *
 429  ******************************************************************************/
 430 
 431 acpi_status
 432 acpi_ns_convert_to_reference(struct acpi_namespace_node *scope,
 433                              union acpi_operand_object *original_object,
 434                              union acpi_operand_object **return_object)
 435 {
 436         union acpi_operand_object *new_object = NULL;
 437         acpi_status status;
 438         struct acpi_namespace_node *node;
 439         union acpi_generic_state scope_info;
 440         char *name;
 441 
 442         ACPI_FUNCTION_NAME(ns_convert_to_reference);
 443 
 444         /* Convert path into internal presentation */
 445 
 446         status =
 447             acpi_ns_internalize_name(original_object->string.pointer, &name);
 448         if (ACPI_FAILURE(status)) {
 449                 return_ACPI_STATUS(status);
 450         }
 451 
 452         /* Find the namespace node */
 453 
 454         scope_info.scope.node =
 455             ACPI_CAST_PTR(struct acpi_namespace_node, scope);
 456         status =
 457             acpi_ns_lookup(&scope_info, name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
 458                            ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
 459                            NULL, &node);
 460         if (ACPI_FAILURE(status)) {
 461 
 462                 /* Check if we are resolving a named reference within a package */
 463 
 464                 ACPI_ERROR_NAMESPACE(&scope_info,
 465                                      original_object->string.pointer, status);
 466                 goto error_exit;
 467         }
 468 
 469         /* Create and init a new internal ACPI object */
 470 
 471         new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
 472         if (!new_object) {
 473                 status = AE_NO_MEMORY;
 474                 goto error_exit;
 475         }
 476         new_object->reference.node = node;
 477         new_object->reference.object = node->object;
 478         new_object->reference.class = ACPI_REFCLASS_NAME;
 479 
 480         /*
 481          * Increase reference of the object if needed (the object is likely a
 482          * null for device nodes).
 483          */
 484         acpi_ut_add_reference(node->object);
 485 
 486 error_exit:
 487         ACPI_FREE(name);
 488         *return_object = new_object;
 489         return (AE_OK);
 490 }

/* [<][>][^][v][top][bottom][index][help] */