linux/drivers/acpi/acpica/utcopy.c
<<
>>
Prefs
   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 - 2021, 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
  16ACPI_MODULE_NAME("utcopy")
  17
  18/* Local prototypes */
  19static acpi_status
  20acpi_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
  24static acpi_status
  25acpi_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
  30static acpi_status
  31acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
  32                                  u8 *buffer, acpi_size *space_used);
  33
  34static acpi_status
  35acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
  36                                union acpi_operand_object **return_obj);
  37
  38static acpi_status
  39acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
  40                                  union acpi_operand_object **internal_object);
  41
  42static acpi_status
  43acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
  44                           union acpi_operand_object *dest_desc);
  45
  46static acpi_status
  47acpi_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
  52static acpi_status
  53acpi_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
  77static acpi_status
  78acpi_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
 211static acpi_status
 212acpi_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
 298static acpi_status
 299acpi_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
 358acpi_status
 359acpi_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
 417static acpi_status
 418acpi_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
 521error_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
 540static acpi_status
 541acpi_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
 602acpi_status
 603acpi_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
 639static acpi_status
 640acpi_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
 790static acpi_status
 791acpi_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
 867error_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
 887static acpi_status
 888acpi_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
 943acpi_status
 944acpi_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}
 977