root/drivers/acpi/acpica/utcopy.c

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

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ut_copy_ielement_to_eelement
  3. acpi_ut_copy_ipackage_to_epackage
  4. acpi_ut_copy_iobject_to_eobject
  5. acpi_ut_copy_esimple_to_isimple
  6. acpi_ut_copy_epackage_to_ipackage
  7. acpi_ut_copy_eobject_to_iobject
  8. acpi_ut_copy_simple_object
  9. acpi_ut_copy_ielement_to_ielement
  10. acpi_ut_copy_ipackage_to_ipackage
  11. acpi_ut_copy_iobject_to_iobject

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Module Name: utcopy - Internal to external object translation utilities
   5  *
   6  * Copyright (C) 2000 - 2019, Intel Corp.
   7  *
   8  *****************************************************************************/
   9 
  10 #include <acpi/acpi.h>
  11 #include "accommon.h"
  12 #include "acnamesp.h"
  13 
  14 
  15 #define _COMPONENT          ACPI_UTILITIES
  16 ACPI_MODULE_NAME("utcopy")
  17 
  18 /* Local prototypes */
  19 static acpi_status
  20 acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
  21                                 union acpi_object *external_object,
  22                                 u8 *data_space, acpi_size *buffer_space_used);
  23 
  24 static acpi_status
  25 acpi_ut_copy_ielement_to_ielement(u8 object_type,
  26                                   union acpi_operand_object *source_object,
  27                                   union acpi_generic_state *state,
  28                                   void *context);
  29 
  30 static acpi_status
  31 acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
  32                                   u8 *buffer, acpi_size *space_used);
  33 
  34 static acpi_status
  35 acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
  36                                 union acpi_operand_object **return_obj);
  37 
  38 static acpi_status
  39 acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
  40                                   union acpi_operand_object **internal_object);
  41 
  42 static acpi_status
  43 acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
  44                            union acpi_operand_object *dest_desc);
  45 
  46 static acpi_status
  47 acpi_ut_copy_ielement_to_eelement(u8 object_type,
  48                                   union acpi_operand_object *source_object,
  49                                   union acpi_generic_state *state,
  50                                   void *context);
  51 
  52 static acpi_status
  53 acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
  54                                   union acpi_operand_object *dest_obj,
  55                                   struct acpi_walk_state *walk_state);
  56 
  57 /*******************************************************************************
  58  *
  59  * FUNCTION:    acpi_ut_copy_isimple_to_esimple
  60  *
  61  * PARAMETERS:  internal_object     - Source object to be copied
  62  *              external_object     - Where to return the copied object
  63  *              data_space          - Where object data is returned (such as
  64  *                                    buffer and string data)
  65  *              buffer_space_used   - Length of data_space that was used
  66  *
  67  * RETURN:      Status
  68  *
  69  * DESCRIPTION: This function is called to copy a simple internal object to
  70  *              an external object.
  71  *
  72  *              The data_space buffer is assumed to have sufficient space for
  73  *              the object.
  74  *
  75  ******************************************************************************/
  76 
  77 static acpi_status
  78 acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
  79                                 union acpi_object *external_object,
  80                                 u8 *data_space, acpi_size *buffer_space_used)
  81 {
  82         acpi_status status = AE_OK;
  83 
  84         ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple);
  85 
  86         *buffer_space_used = 0;
  87 
  88         /*
  89          * Check for NULL object case (could be an uninitialized
  90          * package element)
  91          */
  92         if (!internal_object) {
  93                 return_ACPI_STATUS(AE_OK);
  94         }
  95 
  96         /* Always clear the external object */
  97 
  98         memset(external_object, 0, sizeof(union acpi_object));
  99 
 100         /*
 101          * In general, the external object will be the same type as
 102          * the internal object
 103          */
 104         external_object->type = internal_object->common.type;
 105 
 106         /* However, only a limited number of external types are supported */
 107 
 108         switch (internal_object->common.type) {
 109         case ACPI_TYPE_STRING:
 110 
 111                 external_object->string.pointer = (char *)data_space;
 112                 external_object->string.length = internal_object->string.length;
 113                 *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
 114                                                                   internal_object->
 115                                                                   string.
 116                                                                   length + 1);
 117 
 118                 memcpy((void *)data_space,
 119                        (void *)internal_object->string.pointer,
 120                        (acpi_size)internal_object->string.length + 1);
 121                 break;
 122 
 123         case ACPI_TYPE_BUFFER:
 124 
 125                 external_object->buffer.pointer = data_space;
 126                 external_object->buffer.length = internal_object->buffer.length;
 127                 *buffer_space_used =
 128                     ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string.
 129                                                  length);
 130 
 131                 memcpy((void *)data_space,
 132                        (void *)internal_object->buffer.pointer,
 133                        internal_object->buffer.length);
 134                 break;
 135 
 136         case ACPI_TYPE_INTEGER:
 137 
 138                 external_object->integer.value = internal_object->integer.value;
 139                 break;
 140 
 141         case ACPI_TYPE_LOCAL_REFERENCE:
 142 
 143                 /* This is an object reference. */
 144 
 145                 switch (internal_object->reference.class) {
 146                 case ACPI_REFCLASS_NAME:
 147                         /*
 148                          * For namepath, return the object handle ("reference")
 149                          * We are referring to the namespace node
 150                          */
 151                         external_object->reference.handle =
 152                             internal_object->reference.node;
 153                         external_object->reference.actual_type =
 154                             acpi_ns_get_type(internal_object->reference.node);
 155                         break;
 156 
 157                 default:
 158 
 159                         /* All other reference types are unsupported */
 160 
 161                         return_ACPI_STATUS(AE_TYPE);
 162                 }
 163                 break;
 164 
 165         case ACPI_TYPE_PROCESSOR:
 166 
 167                 external_object->processor.proc_id =
 168                     internal_object->processor.proc_id;
 169                 external_object->processor.pblk_address =
 170                     internal_object->processor.address;
 171                 external_object->processor.pblk_length =
 172                     internal_object->processor.length;
 173                 break;
 174 
 175         case ACPI_TYPE_POWER:
 176 
 177                 external_object->power_resource.system_level =
 178                     internal_object->power_resource.system_level;
 179 
 180                 external_object->power_resource.resource_order =
 181                     internal_object->power_resource.resource_order;
 182                 break;
 183 
 184         default:
 185                 /*
 186                  * There is no corresponding external object type
 187                  */
 188                 ACPI_ERROR((AE_INFO,
 189                             "Unsupported object type, cannot convert to external object: %s",
 190                             acpi_ut_get_type_name(internal_object->common.
 191                                                   type)));
 192 
 193                 return_ACPI_STATUS(AE_SUPPORT);
 194         }
 195 
 196         return_ACPI_STATUS(status);
 197 }
 198 
 199 /*******************************************************************************
 200  *
 201  * FUNCTION:    acpi_ut_copy_ielement_to_eelement
 202  *
 203  * PARAMETERS:  acpi_pkg_callback
 204  *
 205  * RETURN:      Status
 206  *
 207  * DESCRIPTION: Copy one package element to another package element
 208  *
 209  ******************************************************************************/
 210 
 211 static acpi_status
 212 acpi_ut_copy_ielement_to_eelement(u8 object_type,
 213                                   union acpi_operand_object *source_object,
 214                                   union acpi_generic_state *state,
 215                                   void *context)
 216 {
 217         acpi_status status = AE_OK;
 218         struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
 219         acpi_size object_space;
 220         u32 this_index;
 221         union acpi_object *target_object;
 222 
 223         ACPI_FUNCTION_ENTRY();
 224 
 225         this_index = state->pkg.index;
 226         target_object = (union acpi_object *)&((union acpi_object *)
 227                                                (state->pkg.dest_object))->
 228             package.elements[this_index];
 229 
 230         switch (object_type) {
 231         case ACPI_COPY_TYPE_SIMPLE:
 232                 /*
 233                  * This is a simple or null object
 234                  */
 235                 status = acpi_ut_copy_isimple_to_esimple(source_object,
 236                                                          target_object,
 237                                                          info->free_space,
 238                                                          &object_space);
 239                 if (ACPI_FAILURE(status)) {
 240                         return (status);
 241                 }
 242                 break;
 243 
 244         case ACPI_COPY_TYPE_PACKAGE:
 245                 /*
 246                  * Build the package object
 247                  */
 248                 target_object->type = ACPI_TYPE_PACKAGE;
 249                 target_object->package.count = source_object->package.count;
 250                 target_object->package.elements =
 251                     ACPI_CAST_PTR(union acpi_object, info->free_space);
 252 
 253                 /*
 254                  * Pass the new package object back to the package walk routine
 255                  */
 256                 state->pkg.this_target_obj = target_object;
 257 
 258                 /*
 259                  * Save space for the array of objects (Package elements)
 260                  * update the buffer length counter
 261                  */
 262                 object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
 263                                                             target_object->
 264                                                             package.count *
 265                                                             sizeof(union
 266                                                                    acpi_object));
 267                 break;
 268 
 269         default:
 270 
 271                 return (AE_BAD_PARAMETER);
 272         }
 273 
 274         info->free_space += object_space;
 275         info->length += object_space;
 276         return (status);
 277 }
 278 
 279 /*******************************************************************************
 280  *
 281  * FUNCTION:    acpi_ut_copy_ipackage_to_epackage
 282  *
 283  * PARAMETERS:  internal_object     - Pointer to the object we are returning
 284  *              buffer              - Where the object is returned
 285  *              space_used          - Where the object length is returned
 286  *
 287  * RETURN:      Status
 288  *
 289  * DESCRIPTION: This function is called to place a package object in a user
 290  *              buffer. A package object by definition contains other objects.
 291  *
 292  *              The buffer is assumed to have sufficient space for the object.
 293  *              The caller must have verified the buffer length needed using
 294  *              the acpi_ut_get_object_size function before calling this function.
 295  *
 296  ******************************************************************************/
 297 
 298 static acpi_status
 299 acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
 300                                   u8 *buffer, acpi_size *space_used)
 301 {
 302         union acpi_object *external_object;
 303         acpi_status status;
 304         struct acpi_pkg_info info;
 305 
 306         ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage);
 307 
 308         /*
 309          * First package at head of the buffer
 310          */
 311         external_object = ACPI_CAST_PTR(union acpi_object, buffer);
 312 
 313         /*
 314          * Free space begins right after the first package
 315          */
 316         info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
 317         info.free_space = buffer +
 318             ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
 319         info.object_space = 0;
 320         info.num_packages = 1;
 321 
 322         external_object->type = internal_object->common.type;
 323         external_object->package.count = internal_object->package.count;
 324         external_object->package.elements =
 325             ACPI_CAST_PTR(union acpi_object, info.free_space);
 326 
 327         /*
 328          * Leave room for an array of ACPI_OBJECTS in the buffer
 329          * and move the free space past it
 330          */
 331         info.length += (acpi_size)external_object->package.count *
 332             ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
 333         info.free_space += external_object->package.count *
 334             ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
 335 
 336         status = acpi_ut_walk_package_tree(internal_object, external_object,
 337                                            acpi_ut_copy_ielement_to_eelement,
 338                                            &info);
 339 
 340         *space_used = info.length;
 341         return_ACPI_STATUS(status);
 342 }
 343 
 344 /*******************************************************************************
 345  *
 346  * FUNCTION:    acpi_ut_copy_iobject_to_eobject
 347  *
 348  * PARAMETERS:  internal_object     - The internal object to be converted
 349  *              ret_buffer          - Where the object is returned
 350  *
 351  * RETURN:      Status
 352  *
 353  * DESCRIPTION: This function is called to build an API object to be returned
 354  *              to the caller.
 355  *
 356  ******************************************************************************/
 357 
 358 acpi_status
 359 acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object,
 360                                 struct acpi_buffer *ret_buffer)
 361 {
 362         acpi_status status;
 363 
 364         ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject);
 365 
 366         if (internal_object->common.type == ACPI_TYPE_PACKAGE) {
 367                 /*
 368                  * Package object:  Copy all subobjects (including
 369                  * nested packages)
 370                  */
 371                 status = acpi_ut_copy_ipackage_to_epackage(internal_object,
 372                                                            ret_buffer->pointer,
 373                                                            &ret_buffer->length);
 374         } else {
 375                 /*
 376                  * Build a simple object (no nested objects)
 377                  */
 378                 status = acpi_ut_copy_isimple_to_esimple(internal_object,
 379                                                          ACPI_CAST_PTR(union
 380                                                                        acpi_object,
 381                                                                        ret_buffer->
 382                                                                        pointer),
 383                                                          ACPI_ADD_PTR(u8,
 384                                                                       ret_buffer->
 385                                                                       pointer,
 386                                                                       ACPI_ROUND_UP_TO_NATIVE_WORD
 387                                                                       (sizeof
 388                                                                        (union
 389                                                                         acpi_object))),
 390                                                          &ret_buffer->length);
 391                 /*
 392                  * build simple does not include the object size in the length
 393                  * so we add it in here
 394                  */
 395                 ret_buffer->length += sizeof(union acpi_object);
 396         }
 397 
 398         return_ACPI_STATUS(status);
 399 }
 400 
 401 /*******************************************************************************
 402  *
 403  * FUNCTION:    acpi_ut_copy_esimple_to_isimple
 404  *
 405  * PARAMETERS:  external_object     - The external object to be converted
 406  *              ret_internal_object - Where the internal object is returned
 407  *
 408  * RETURN:      Status
 409  *
 410  * DESCRIPTION: This function copies an external object to an internal one.
 411  *              NOTE: Pointers can be copied, we don't need to copy data.
 412  *              (The pointers have to be valid in our address space no matter
 413  *              what we do with them!)
 414  *
 415  ******************************************************************************/
 416 
 417 static acpi_status
 418 acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
 419                                 union acpi_operand_object **ret_internal_object)
 420 {
 421         union acpi_operand_object *internal_object;
 422 
 423         ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple);
 424 
 425         /*
 426          * Simple types supported are: String, Buffer, Integer
 427          */
 428         switch (external_object->type) {
 429         case ACPI_TYPE_STRING:
 430         case ACPI_TYPE_BUFFER:
 431         case ACPI_TYPE_INTEGER:
 432         case ACPI_TYPE_LOCAL_REFERENCE:
 433 
 434                 internal_object = acpi_ut_create_internal_object((u8)
 435                                                                  external_object->
 436                                                                  type);
 437                 if (!internal_object) {
 438                         return_ACPI_STATUS(AE_NO_MEMORY);
 439                 }
 440                 break;
 441 
 442         case ACPI_TYPE_ANY:     /* This is the case for a NULL object */
 443 
 444                 *ret_internal_object = NULL;
 445                 return_ACPI_STATUS(AE_OK);
 446 
 447         default:
 448 
 449                 /* All other types are not supported */
 450 
 451                 ACPI_ERROR((AE_INFO,
 452                             "Unsupported object type, cannot convert to internal object: %s",
 453                             acpi_ut_get_type_name(external_object->type)));
 454 
 455                 return_ACPI_STATUS(AE_SUPPORT);
 456         }
 457 
 458         /* Must COPY string and buffer contents */
 459 
 460         switch (external_object->type) {
 461         case ACPI_TYPE_STRING:
 462 
 463                 internal_object->string.pointer =
 464                     ACPI_ALLOCATE_ZEROED((acpi_size)
 465                                          external_object->string.length + 1);
 466 
 467                 if (!internal_object->string.pointer) {
 468                         goto error_exit;
 469                 }
 470 
 471                 memcpy(internal_object->string.pointer,
 472                        external_object->string.pointer,
 473                        external_object->string.length);
 474 
 475                 internal_object->string.length = external_object->string.length;
 476                 break;
 477 
 478         case ACPI_TYPE_BUFFER:
 479 
 480                 internal_object->buffer.pointer =
 481                     ACPI_ALLOCATE_ZEROED(external_object->buffer.length);
 482                 if (!internal_object->buffer.pointer) {
 483                         goto error_exit;
 484                 }
 485 
 486                 memcpy(internal_object->buffer.pointer,
 487                        external_object->buffer.pointer,
 488                        external_object->buffer.length);
 489 
 490                 internal_object->buffer.length = external_object->buffer.length;
 491 
 492                 /* Mark buffer data valid */
 493 
 494                 internal_object->buffer.flags |= AOPOBJ_DATA_VALID;
 495                 break;
 496 
 497         case ACPI_TYPE_INTEGER:
 498 
 499                 internal_object->integer.value = external_object->integer.value;
 500                 break;
 501 
 502         case ACPI_TYPE_LOCAL_REFERENCE:
 503 
 504                 /* An incoming reference is defined to be a namespace node */
 505 
 506                 internal_object->reference.class = ACPI_REFCLASS_REFOF;
 507                 internal_object->reference.object =
 508                     external_object->reference.handle;
 509                 break;
 510 
 511         default:
 512 
 513                 /* Other types can't get here */
 514 
 515                 break;
 516         }
 517 
 518         *ret_internal_object = internal_object;
 519         return_ACPI_STATUS(AE_OK);
 520 
 521 error_exit:
 522         acpi_ut_remove_reference(internal_object);
 523         return_ACPI_STATUS(AE_NO_MEMORY);
 524 }
 525 
 526 /*******************************************************************************
 527  *
 528  * FUNCTION:    acpi_ut_copy_epackage_to_ipackage
 529  *
 530  * PARAMETERS:  external_object     - The external object to be converted
 531  *              internal_object     - Where the internal object is returned
 532  *
 533  * RETURN:      Status
 534  *
 535  * DESCRIPTION: Copy an external package object to an internal package.
 536  *              Handles nested packages.
 537  *
 538  ******************************************************************************/
 539 
 540 static acpi_status
 541 acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
 542                                   union acpi_operand_object **internal_object)
 543 {
 544         acpi_status status = AE_OK;
 545         union acpi_operand_object *package_object;
 546         union acpi_operand_object **package_elements;
 547         u32 i;
 548 
 549         ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
 550 
 551         /* Create the package object */
 552 
 553         package_object =
 554             acpi_ut_create_package_object(external_object->package.count);
 555         if (!package_object) {
 556                 return_ACPI_STATUS(AE_NO_MEMORY);
 557         }
 558 
 559         package_elements = package_object->package.elements;
 560 
 561         /*
 562          * Recursive implementation. Probably ok, since nested external
 563          * packages as parameters should be very rare.
 564          */
 565         for (i = 0; i < external_object->package.count; i++) {
 566                 status =
 567                     acpi_ut_copy_eobject_to_iobject(&external_object->package.
 568                                                     elements[i],
 569                                                     &package_elements[i]);
 570                 if (ACPI_FAILURE(status)) {
 571 
 572                         /* Truncate package and delete it */
 573 
 574                         package_object->package.count = i;
 575                         package_elements[i] = NULL;
 576                         acpi_ut_remove_reference(package_object);
 577                         return_ACPI_STATUS(status);
 578                 }
 579         }
 580 
 581         /* Mark package data valid */
 582 
 583         package_object->package.flags |= AOPOBJ_DATA_VALID;
 584 
 585         *internal_object = package_object;
 586         return_ACPI_STATUS(status);
 587 }
 588 
 589 /*******************************************************************************
 590  *
 591  * FUNCTION:    acpi_ut_copy_eobject_to_iobject
 592  *
 593  * PARAMETERS:  external_object     - The external object to be converted
 594  *              internal_object     - Where the internal object is returned
 595  *
 596  * RETURN:      Status
 597  *
 598  * DESCRIPTION: Converts an external object to an internal object.
 599  *
 600  ******************************************************************************/
 601 
 602 acpi_status
 603 acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
 604                                 union acpi_operand_object **internal_object)
 605 {
 606         acpi_status status;
 607 
 608         ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
 609 
 610         if (external_object->type == ACPI_TYPE_PACKAGE) {
 611                 status =
 612                     acpi_ut_copy_epackage_to_ipackage(external_object,
 613                                                       internal_object);
 614         } else {
 615                 /*
 616                  * Build a simple object (no nested objects)
 617                  */
 618                 status = acpi_ut_copy_esimple_to_isimple(external_object,
 619                                                          internal_object);
 620         }
 621 
 622         return_ACPI_STATUS(status);
 623 }
 624 
 625 /*******************************************************************************
 626  *
 627  * FUNCTION:    acpi_ut_copy_simple_object
 628  *
 629  * PARAMETERS:  source_desc         - The internal object to be copied
 630  *              dest_desc           - New target object
 631  *
 632  * RETURN:      Status
 633  *
 634  * DESCRIPTION: Simple copy of one internal object to another. Reference count
 635  *              of the destination object is preserved.
 636  *
 637  ******************************************************************************/
 638 
 639 static acpi_status
 640 acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
 641                            union acpi_operand_object *dest_desc)
 642 {
 643         u16 reference_count;
 644         union acpi_operand_object *next_object;
 645         acpi_status status;
 646         acpi_size copy_size;
 647 
 648         /* Save fields from destination that we don't want to overwrite */
 649 
 650         reference_count = dest_desc->common.reference_count;
 651         next_object = dest_desc->common.next_object;
 652 
 653         /*
 654          * Copy the entire source object over the destination object.
 655          * Note: Source can be either an operand object or namespace node.
 656          */
 657         copy_size = sizeof(union acpi_operand_object);
 658         if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_NAMED) {
 659                 copy_size = sizeof(struct acpi_namespace_node);
 660         }
 661 
 662         memcpy(ACPI_CAST_PTR(char, dest_desc),
 663                ACPI_CAST_PTR(char, source_desc), copy_size);
 664 
 665         /* Restore the saved fields */
 666 
 667         dest_desc->common.reference_count = reference_count;
 668         dest_desc->common.next_object = next_object;
 669 
 670         /* New object is not static, regardless of source */
 671 
 672         dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
 673 
 674         /* Handle the objects with extra data */
 675 
 676         switch (dest_desc->common.type) {
 677         case ACPI_TYPE_BUFFER:
 678                 /*
 679                  * Allocate and copy the actual buffer if and only if:
 680                  * 1) There is a valid buffer pointer
 681                  * 2) The buffer has a length > 0
 682                  */
 683                 if ((source_desc->buffer.pointer) &&
 684                     (source_desc->buffer.length)) {
 685                         dest_desc->buffer.pointer =
 686                             ACPI_ALLOCATE(source_desc->buffer.length);
 687                         if (!dest_desc->buffer.pointer) {
 688                                 return (AE_NO_MEMORY);
 689                         }
 690 
 691                         /* Copy the actual buffer data */
 692 
 693                         memcpy(dest_desc->buffer.pointer,
 694                                source_desc->buffer.pointer,
 695                                source_desc->buffer.length);
 696                 }
 697                 break;
 698 
 699         case ACPI_TYPE_STRING:
 700                 /*
 701                  * Allocate and copy the actual string if and only if:
 702                  * 1) There is a valid string pointer
 703                  * (Pointer to a NULL string is allowed)
 704                  */
 705                 if (source_desc->string.pointer) {
 706                         dest_desc->string.pointer =
 707                             ACPI_ALLOCATE((acpi_size)source_desc->string.
 708                                           length + 1);
 709                         if (!dest_desc->string.pointer) {
 710                                 return (AE_NO_MEMORY);
 711                         }
 712 
 713                         /* Copy the actual string data */
 714 
 715                         memcpy(dest_desc->string.pointer,
 716                                source_desc->string.pointer,
 717                                (acpi_size)source_desc->string.length + 1);
 718                 }
 719                 break;
 720 
 721         case ACPI_TYPE_LOCAL_REFERENCE:
 722                 /*
 723                  * We copied the reference object, so we now must add a reference
 724                  * to the object pointed to by the reference
 725                  *
 726                  * DDBHandle reference (from Load/load_table) is a special reference,
 727                  * it does not have a Reference.Object, so does not need to
 728                  * increase the reference count
 729                  */
 730                 if (source_desc->reference.class == ACPI_REFCLASS_TABLE) {
 731                         break;
 732                 }
 733 
 734                 acpi_ut_add_reference(source_desc->reference.object);
 735                 break;
 736 
 737         case ACPI_TYPE_REGION:
 738                 /*
 739                  * We copied the Region Handler, so we now must add a reference
 740                  */
 741                 if (dest_desc->region.handler) {
 742                         acpi_ut_add_reference(dest_desc->region.handler);
 743                 }
 744                 break;
 745 
 746                 /*
 747                  * For Mutex and Event objects, we cannot simply copy the underlying
 748                  * OS object. We must create a new one.
 749                  */
 750         case ACPI_TYPE_MUTEX:
 751 
 752                 status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex);
 753                 if (ACPI_FAILURE(status)) {
 754                         return (status);
 755                 }
 756                 break;
 757 
 758         case ACPI_TYPE_EVENT:
 759 
 760                 status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
 761                                                   &dest_desc->event.
 762                                                   os_semaphore);
 763                 if (ACPI_FAILURE(status)) {
 764                         return (status);
 765                 }
 766                 break;
 767 
 768         default:
 769 
 770                 /* Nothing to do for other simple objects */
 771 
 772                 break;
 773         }
 774 
 775         return (AE_OK);
 776 }
 777 
 778 /*******************************************************************************
 779  *
 780  * FUNCTION:    acpi_ut_copy_ielement_to_ielement
 781  *
 782  * PARAMETERS:  acpi_pkg_callback
 783  *
 784  * RETURN:      Status
 785  *
 786  * DESCRIPTION: Copy one package element to another package element
 787  *
 788  ******************************************************************************/
 789 
 790 static acpi_status
 791 acpi_ut_copy_ielement_to_ielement(u8 object_type,
 792                                   union acpi_operand_object *source_object,
 793                                   union acpi_generic_state *state,
 794                                   void *context)
 795 {
 796         acpi_status status = AE_OK;
 797         u32 this_index;
 798         union acpi_operand_object **this_target_ptr;
 799         union acpi_operand_object *target_object;
 800 
 801         ACPI_FUNCTION_ENTRY();
 802 
 803         this_index = state->pkg.index;
 804         this_target_ptr = (union acpi_operand_object **)
 805             &state->pkg.dest_object->package.elements[this_index];
 806 
 807         switch (object_type) {
 808         case ACPI_COPY_TYPE_SIMPLE:
 809 
 810                 /* A null source object indicates a (legal) null package element */
 811 
 812                 if (source_object) {
 813                         /*
 814                          * This is a simple object, just copy it
 815                          */
 816                         target_object =
 817                             acpi_ut_create_internal_object(source_object->
 818                                                            common.type);
 819                         if (!target_object) {
 820                                 return (AE_NO_MEMORY);
 821                         }
 822 
 823                         status =
 824                             acpi_ut_copy_simple_object(source_object,
 825                                                        target_object);
 826                         if (ACPI_FAILURE(status)) {
 827                                 goto error_exit;
 828                         }
 829 
 830                         *this_target_ptr = target_object;
 831                 } else {
 832                         /* Pass through a null element */
 833 
 834                         *this_target_ptr = NULL;
 835                 }
 836                 break;
 837 
 838         case ACPI_COPY_TYPE_PACKAGE:
 839                 /*
 840                  * This object is a package - go down another nesting level
 841                  * Create and build the package object
 842                  */
 843                 target_object =
 844                     acpi_ut_create_package_object(source_object->package.count);
 845                 if (!target_object) {
 846                         return (AE_NO_MEMORY);
 847                 }
 848 
 849                 target_object->common.flags = source_object->common.flags;
 850 
 851                 /* Pass the new package object back to the package walk routine */
 852 
 853                 state->pkg.this_target_obj = target_object;
 854 
 855                 /* Store the object pointer in the parent package object */
 856 
 857                 *this_target_ptr = target_object;
 858                 break;
 859 
 860         default:
 861 
 862                 return (AE_BAD_PARAMETER);
 863         }
 864 
 865         return (status);
 866 
 867 error_exit:
 868         acpi_ut_remove_reference(target_object);
 869         return (status);
 870 }
 871 
 872 /*******************************************************************************
 873  *
 874  * FUNCTION:    acpi_ut_copy_ipackage_to_ipackage
 875  *
 876  * PARAMETERS:  source_obj      - Pointer to the source package object
 877  *              dest_obj        - Where the internal object is returned
 878  *              walk_state      - Current Walk state descriptor
 879  *
 880  * RETURN:      Status
 881  *
 882  * DESCRIPTION: This function is called to copy an internal package object
 883  *              into another internal package object.
 884  *
 885  ******************************************************************************/
 886 
 887 static acpi_status
 888 acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
 889                                   union acpi_operand_object *dest_obj,
 890                                   struct acpi_walk_state *walk_state)
 891 {
 892         acpi_status status = AE_OK;
 893 
 894         ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage);
 895 
 896         dest_obj->common.type = source_obj->common.type;
 897         dest_obj->common.flags = source_obj->common.flags;
 898         dest_obj->package.count = source_obj->package.count;
 899 
 900         /*
 901          * Create the object array and walk the source package tree
 902          */
 903         dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
 904                                                            source_obj->package.
 905                                                            count +
 906                                                            1) * sizeof(void *));
 907         if (!dest_obj->package.elements) {
 908                 ACPI_ERROR((AE_INFO, "Package allocation failure"));
 909                 return_ACPI_STATUS(AE_NO_MEMORY);
 910         }
 911 
 912         /*
 913          * Copy the package element-by-element by walking the package "tree".
 914          * This handles nested packages of arbitrary depth.
 915          */
 916         status = acpi_ut_walk_package_tree(source_obj, dest_obj,
 917                                            acpi_ut_copy_ielement_to_ielement,
 918                                            walk_state);
 919         if (ACPI_FAILURE(status)) {
 920 
 921                 /* On failure, delete the destination package object */
 922 
 923                 acpi_ut_remove_reference(dest_obj);
 924         }
 925 
 926         return_ACPI_STATUS(status);
 927 }
 928 
 929 /*******************************************************************************
 930  *
 931  * FUNCTION:    acpi_ut_copy_iobject_to_iobject
 932  *
 933  * PARAMETERS:  source_desc         - The internal object to be copied
 934  *              dest_desc           - Where the copied object is returned
 935  *              walk_state          - Current walk state
 936  *
 937  * RETURN:      Status
 938  *
 939  * DESCRIPTION: Copy an internal object to a new internal object
 940  *
 941  ******************************************************************************/
 942 
 943 acpi_status
 944 acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
 945                                 union acpi_operand_object **dest_desc,
 946                                 struct acpi_walk_state *walk_state)
 947 {
 948         acpi_status status = AE_OK;
 949 
 950         ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject);
 951 
 952         /* Create the top level object */
 953 
 954         *dest_desc = acpi_ut_create_internal_object(source_desc->common.type);
 955         if (!*dest_desc) {
 956                 return_ACPI_STATUS(AE_NO_MEMORY);
 957         }
 958 
 959         /* Copy the object and possible subobjects */
 960 
 961         if (source_desc->common.type == ACPI_TYPE_PACKAGE) {
 962                 status =
 963                     acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc,
 964                                                       walk_state);
 965         } else {
 966                 status = acpi_ut_copy_simple_object(source_desc, *dest_desc);
 967         }
 968 
 969         /* Delete the allocated object if copy failed */
 970 
 971         if (ACPI_FAILURE(status)) {
 972                 acpi_ut_remove_reference(*dest_desc);
 973         }
 974 
 975         return_ACPI_STATUS(status);
 976 }

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