root/drivers/acpi/acpica/exconcat.c

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

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ex_convert_to_object_type_string
  3. acpi_ex_concat_template

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Module Name: exconcat - Concatenate-type AML operators
   5  *
   6  * Copyright (C) 2000 - 2019, Intel Corp.
   7  *
   8  *****************************************************************************/
   9 
  10 #include <acpi/acpi.h>
  11 #include "accommon.h"
  12 #include "acinterp.h"
  13 #include "amlresrc.h"
  14 
  15 #define _COMPONENT          ACPI_EXECUTER
  16 ACPI_MODULE_NAME("exconcat")
  17 
  18 /* Local Prototypes */
  19 static acpi_status
  20 acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc,
  21                                       union acpi_operand_object **result_desc);
  22 
  23 /*******************************************************************************
  24  *
  25  * FUNCTION:    acpi_ex_do_concatenate
  26  *
  27  * PARAMETERS:  operand0            - First source object
  28  *              operand1            - Second source object
  29  *              actual_return_desc  - Where to place the return object
  30  *              walk_state          - Current walk state
  31  *
  32  * RETURN:      Status
  33  *
  34  * DESCRIPTION: Concatenate two objects with the ACPI-defined conversion
  35  *              rules as necessary.
  36  * NOTE:
  37  * Per the ACPI spec (up to 6.1), Concatenate only supports Integer,
  38  * String, and Buffer objects. However, we support all objects here
  39  * as an extension. This improves the usefulness of both Concatenate
  40  * and the Printf/Fprintf macros. The extension returns a string
  41  * describing the object type for the other objects.
  42  * 02/2016.
  43  *
  44  ******************************************************************************/
  45 
  46 acpi_status
  47 acpi_ex_do_concatenate(union acpi_operand_object *operand0,
  48                        union acpi_operand_object *operand1,
  49                        union acpi_operand_object **actual_return_desc,
  50                        struct acpi_walk_state *walk_state)
  51 {
  52         union acpi_operand_object *local_operand0 = operand0;
  53         union acpi_operand_object *local_operand1 = operand1;
  54         union acpi_operand_object *temp_operand1 = NULL;
  55         union acpi_operand_object *return_desc;
  56         char *buffer;
  57         acpi_object_type operand0_type;
  58         acpi_object_type operand1_type;
  59         acpi_status status;
  60 
  61         ACPI_FUNCTION_TRACE(ex_do_concatenate);
  62 
  63         /* Operand 0 preprocessing */
  64 
  65         switch (operand0->common.type) {
  66         case ACPI_TYPE_INTEGER:
  67         case ACPI_TYPE_STRING:
  68         case ACPI_TYPE_BUFFER:
  69 
  70                 operand0_type = operand0->common.type;
  71                 break;
  72 
  73         default:
  74 
  75                 /* For all other types, get the "object type" string */
  76 
  77                 status =
  78                     acpi_ex_convert_to_object_type_string(operand0,
  79                                                           &local_operand0);
  80                 if (ACPI_FAILURE(status)) {
  81                         goto cleanup;
  82                 }
  83 
  84                 operand0_type = ACPI_TYPE_STRING;
  85                 break;
  86         }
  87 
  88         /* Operand 1 preprocessing */
  89 
  90         switch (operand1->common.type) {
  91         case ACPI_TYPE_INTEGER:
  92         case ACPI_TYPE_STRING:
  93         case ACPI_TYPE_BUFFER:
  94 
  95                 operand1_type = operand1->common.type;
  96                 break;
  97 
  98         default:
  99 
 100                 /* For all other types, get the "object type" string */
 101 
 102                 status =
 103                     acpi_ex_convert_to_object_type_string(operand1,
 104                                                           &local_operand1);
 105                 if (ACPI_FAILURE(status)) {
 106                         goto cleanup;
 107                 }
 108 
 109                 operand1_type = ACPI_TYPE_STRING;
 110                 break;
 111         }
 112 
 113         /*
 114          * Convert the second operand if necessary. The first operand (0)
 115          * determines the type of the second operand (1) (See the Data Types
 116          * section of the ACPI specification). Both object types are
 117          * guaranteed to be either Integer/String/Buffer by the operand
 118          * resolution mechanism.
 119          */
 120         switch (operand0_type) {
 121         case ACPI_TYPE_INTEGER:
 122 
 123                 status =
 124                     acpi_ex_convert_to_integer(local_operand1, &temp_operand1,
 125                                                ACPI_IMPLICIT_CONVERSION);
 126                 break;
 127 
 128         case ACPI_TYPE_BUFFER:
 129 
 130                 status =
 131                     acpi_ex_convert_to_buffer(local_operand1, &temp_operand1);
 132                 break;
 133 
 134         case ACPI_TYPE_STRING:
 135 
 136                 switch (operand1_type) {
 137                 case ACPI_TYPE_INTEGER:
 138                 case ACPI_TYPE_STRING:
 139                 case ACPI_TYPE_BUFFER:
 140 
 141                         /* Other types have already been converted to string */
 142 
 143                         status =
 144                             acpi_ex_convert_to_string(local_operand1,
 145                                                       &temp_operand1,
 146                                                       ACPI_IMPLICIT_CONVERT_HEX);
 147                         break;
 148 
 149                 default:
 150 
 151                         status = AE_OK;
 152                         break;
 153                 }
 154                 break;
 155 
 156         default:
 157 
 158                 ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
 159                             operand0->common.type));
 160                 status = AE_AML_INTERNAL;
 161         }
 162 
 163         if (ACPI_FAILURE(status)) {
 164                 goto cleanup;
 165         }
 166 
 167         /* Take care with any newly created operand objects */
 168 
 169         if ((local_operand1 != operand1) && (local_operand1 != temp_operand1)) {
 170                 acpi_ut_remove_reference(local_operand1);
 171         }
 172 
 173         local_operand1 = temp_operand1;
 174 
 175         /*
 176          * Both operands are now known to be the same object type
 177          * (Both are Integer, String, or Buffer), and we can now perform
 178          * the concatenation.
 179          *
 180          * There are three cases to handle, as per the ACPI spec:
 181          *
 182          * 1) Two Integers concatenated to produce a new Buffer
 183          * 2) Two Strings concatenated to produce a new String
 184          * 3) Two Buffers concatenated to produce a new Buffer
 185          */
 186         switch (operand0_type) {
 187         case ACPI_TYPE_INTEGER:
 188 
 189                 /* Result of two Integers is a Buffer */
 190                 /* Need enough buffer space for two integers */
 191 
 192                 return_desc = acpi_ut_create_buffer_object((acpi_size)
 193                                                            ACPI_MUL_2
 194                                                            (acpi_gbl_integer_byte_width));
 195                 if (!return_desc) {
 196                         status = AE_NO_MEMORY;
 197                         goto cleanup;
 198                 }
 199 
 200                 buffer = (char *)return_desc->buffer.pointer;
 201 
 202                 /* Copy the first integer, LSB first */
 203 
 204                 memcpy(buffer, &operand0->integer.value,
 205                        acpi_gbl_integer_byte_width);
 206 
 207                 /* Copy the second integer (LSB first) after the first */
 208 
 209                 memcpy(buffer + acpi_gbl_integer_byte_width,
 210                        &local_operand1->integer.value,
 211                        acpi_gbl_integer_byte_width);
 212                 break;
 213 
 214         case ACPI_TYPE_STRING:
 215 
 216                 /* Result of two Strings is a String */
 217 
 218                 return_desc = acpi_ut_create_string_object(((acpi_size)
 219                                                             local_operand0->
 220                                                             string.length +
 221                                                             local_operand1->
 222                                                             string.length));
 223                 if (!return_desc) {
 224                         status = AE_NO_MEMORY;
 225                         goto cleanup;
 226                 }
 227 
 228                 buffer = return_desc->string.pointer;
 229 
 230                 /* Concatenate the strings */
 231 
 232                 strcpy(buffer, local_operand0->string.pointer);
 233                 strcat(buffer, local_operand1->string.pointer);
 234                 break;
 235 
 236         case ACPI_TYPE_BUFFER:
 237 
 238                 /* Result of two Buffers is a Buffer */
 239 
 240                 return_desc = acpi_ut_create_buffer_object(((acpi_size)
 241                                                             operand0->buffer.
 242                                                             length +
 243                                                             local_operand1->
 244                                                             buffer.length));
 245                 if (!return_desc) {
 246                         status = AE_NO_MEMORY;
 247                         goto cleanup;
 248                 }
 249 
 250                 buffer = (char *)return_desc->buffer.pointer;
 251 
 252                 /* Concatenate the buffers */
 253 
 254                 memcpy(buffer, operand0->buffer.pointer,
 255                        operand0->buffer.length);
 256                 memcpy(buffer + operand0->buffer.length,
 257                        local_operand1->buffer.pointer,
 258                        local_operand1->buffer.length);
 259                 break;
 260 
 261         default:
 262 
 263                 /* Invalid object type, should not happen here */
 264 
 265                 ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
 266                             operand0->common.type));
 267                 status = AE_AML_INTERNAL;
 268                 goto cleanup;
 269         }
 270 
 271         *actual_return_desc = return_desc;
 272 
 273 cleanup:
 274         if (local_operand0 != operand0) {
 275                 acpi_ut_remove_reference(local_operand0);
 276         }
 277 
 278         if (local_operand1 != operand1) {
 279                 acpi_ut_remove_reference(local_operand1);
 280         }
 281 
 282         return_ACPI_STATUS(status);
 283 }
 284 
 285 /*******************************************************************************
 286  *
 287  * FUNCTION:    acpi_ex_convert_to_object_type_string
 288  *
 289  * PARAMETERS:  obj_desc            - Object to be converted
 290  *              return_desc         - Where to place the return object
 291  *
 292  * RETURN:      Status
 293  *
 294  * DESCRIPTION: Convert an object of arbitrary type to a string object that
 295  *              contains the namestring for the object. Used for the
 296  *              concatenate operator.
 297  *
 298  ******************************************************************************/
 299 
 300 static acpi_status
 301 acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc,
 302                                       union acpi_operand_object **result_desc)
 303 {
 304         union acpi_operand_object *return_desc;
 305         const char *type_string;
 306 
 307         type_string = acpi_ut_get_type_name(obj_desc->common.type);
 308 
 309         return_desc = acpi_ut_create_string_object(((acpi_size)strlen(type_string) + 9));       /* 9 For "[ Object]" */
 310         if (!return_desc) {
 311                 return (AE_NO_MEMORY);
 312         }
 313 
 314         strcpy(return_desc->string.pointer, "[");
 315         strcat(return_desc->string.pointer, type_string);
 316         strcat(return_desc->string.pointer, " Object]");
 317 
 318         *result_desc = return_desc;
 319         return (AE_OK);
 320 }
 321 
 322 /*******************************************************************************
 323  *
 324  * FUNCTION:    acpi_ex_concat_template
 325  *
 326  * PARAMETERS:  operand0            - First source object
 327  *              operand1            - Second source object
 328  *              actual_return_desc  - Where to place the return object
 329  *              walk_state          - Current walk state
 330  *
 331  * RETURN:      Status
 332  *
 333  * DESCRIPTION: Concatenate two resource templates
 334  *
 335  ******************************************************************************/
 336 
 337 acpi_status
 338 acpi_ex_concat_template(union acpi_operand_object *operand0,
 339                         union acpi_operand_object *operand1,
 340                         union acpi_operand_object **actual_return_desc,
 341                         struct acpi_walk_state *walk_state)
 342 {
 343         acpi_status status;
 344         union acpi_operand_object *return_desc;
 345         u8 *new_buf;
 346         u8 *end_tag;
 347         acpi_size length0;
 348         acpi_size length1;
 349         acpi_size new_length;
 350 
 351         ACPI_FUNCTION_TRACE(ex_concat_template);
 352 
 353         /*
 354          * Find the end_tag descriptor in each resource template.
 355          * Note1: returned pointers point TO the end_tag, not past it.
 356          * Note2: zero-length buffers are allowed; treated like one end_tag
 357          */
 358 
 359         /* Get the length of the first resource template */
 360 
 361         status = acpi_ut_get_resource_end_tag(operand0, &end_tag);
 362         if (ACPI_FAILURE(status)) {
 363                 return_ACPI_STATUS(status);
 364         }
 365 
 366         length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer);
 367 
 368         /* Get the length of the second resource template */
 369 
 370         status = acpi_ut_get_resource_end_tag(operand1, &end_tag);
 371         if (ACPI_FAILURE(status)) {
 372                 return_ACPI_STATUS(status);
 373         }
 374 
 375         length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer);
 376 
 377         /* Combine both lengths, minimum size will be 2 for end_tag */
 378 
 379         new_length = length0 + length1 + sizeof(struct aml_resource_end_tag);
 380 
 381         /* Create a new buffer object for the result (with one end_tag) */
 382 
 383         return_desc = acpi_ut_create_buffer_object(new_length);
 384         if (!return_desc) {
 385                 return_ACPI_STATUS(AE_NO_MEMORY);
 386         }
 387 
 388         /*
 389          * Copy the templates to the new buffer, 0 first, then 1 follows. One
 390          * end_tag descriptor is copied from Operand1.
 391          */
 392         new_buf = return_desc->buffer.pointer;
 393         memcpy(new_buf, operand0->buffer.pointer, length0);
 394         memcpy(new_buf + length0, operand1->buffer.pointer, length1);
 395 
 396         /* Insert end_tag and set the checksum to zero, means "ignore checksum" */
 397 
 398         new_buf[new_length - 1] = 0;
 399         new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
 400 
 401         /* Return the completed resource template */
 402 
 403         *actual_return_desc = return_desc;
 404         return_ACPI_STATUS(AE_OK);
 405 }

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