1 /******************************************************************************
   2  *
   3  * Module Name: utcopy - Internal to external object translation utilities
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 #define __UTCOPY_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acnamesp.h"
  49 
  50 
  51 #define _COMPONENT          ACPI_UTILITIES
  52         ACPI_MODULE_NAME    ("utcopy")
  53 
  54 /* Local prototypes */
  55 
  56 static ACPI_STATUS
  57 AcpiUtCopyIsimpleToEsimple (
  58     ACPI_OPERAND_OBJECT     *InternalObject,
  59     ACPI_OBJECT             *ExternalObject,
  60     UINT8                   *DataSpace,
  61     ACPI_SIZE               *BufferSpaceUsed);
  62 
  63 static ACPI_STATUS
  64 AcpiUtCopyIelementToIelement (
  65     UINT8                   ObjectType,
  66     ACPI_OPERAND_OBJECT     *SourceObject,
  67     ACPI_GENERIC_STATE      *State,
  68     void                    *Context);
  69 
  70 static ACPI_STATUS
  71 AcpiUtCopyIpackageToEpackage (
  72     ACPI_OPERAND_OBJECT     *InternalObject,
  73     UINT8                   *Buffer,
  74     ACPI_SIZE               *SpaceUsed);
  75 
  76 static ACPI_STATUS
  77 AcpiUtCopyEsimpleToIsimple(
  78     ACPI_OBJECT             *UserObj,
  79     ACPI_OPERAND_OBJECT     **ReturnObj);
  80 
  81 static ACPI_STATUS
  82 AcpiUtCopyEpackageToIpackage (
  83     ACPI_OBJECT             *ExternalObject,
  84     ACPI_OPERAND_OBJECT     **InternalObject);
  85 
  86 static ACPI_STATUS
  87 AcpiUtCopySimpleObject (
  88     ACPI_OPERAND_OBJECT     *SourceDesc,
  89     ACPI_OPERAND_OBJECT     *DestDesc);
  90 
  91 static ACPI_STATUS
  92 AcpiUtCopyIelementToEelement (
  93     UINT8                   ObjectType,
  94     ACPI_OPERAND_OBJECT     *SourceObject,
  95     ACPI_GENERIC_STATE      *State,
  96     void                    *Context);
  97 
  98 static ACPI_STATUS
  99 AcpiUtCopyIpackageToIpackage (
 100     ACPI_OPERAND_OBJECT     *SourceObj,
 101     ACPI_OPERAND_OBJECT     *DestObj,
 102     ACPI_WALK_STATE         *WalkState);
 103 
 104 
 105 /*******************************************************************************
 106  *
 107  * FUNCTION:    AcpiUtCopyIsimpleToEsimple
 108  *
 109  * PARAMETERS:  InternalObject      - Source object to be copied
 110  *              ExternalObject      - Where to return the copied object
 111  *              DataSpace           - Where object data is returned (such as
 112  *                                    buffer and string data)
 113  *              BufferSpaceUsed     - Length of DataSpace that was used
 114  *
 115  * RETURN:      Status
 116  *
 117  * DESCRIPTION: This function is called to copy a simple internal object to
 118  *              an external object.
 119  *
 120  *              The DataSpace buffer is assumed to have sufficient space for
 121  *              the object.
 122  *
 123  ******************************************************************************/
 124 
 125 static ACPI_STATUS
 126 AcpiUtCopyIsimpleToEsimple (
 127     ACPI_OPERAND_OBJECT     *InternalObject,
 128     ACPI_OBJECT             *ExternalObject,
 129     UINT8                   *DataSpace,
 130     ACPI_SIZE               *BufferSpaceUsed)
 131 {
 132     ACPI_STATUS             Status = AE_OK;
 133 
 134 
 135     ACPI_FUNCTION_TRACE (UtCopyIsimpleToEsimple);
 136 
 137 
 138     *BufferSpaceUsed = 0;
 139 
 140     /*
 141      * Check for NULL object case (could be an uninitialized
 142      * package element)
 143      */
 144     if (!InternalObject)
 145     {
 146         return_ACPI_STATUS (AE_OK);
 147     }
 148 
 149     /* Always clear the external object */
 150 
 151     ACPI_MEMSET (ExternalObject, 0, sizeof (ACPI_OBJECT));
 152 
 153     /*
 154      * In general, the external object will be the same type as
 155      * the internal object
 156      */
 157     ExternalObject->Type = InternalObject->Common.Type;
 158 
 159     /* However, only a limited number of external types are supported */
 160 
 161     switch (InternalObject->Common.Type)
 162     {
 163     case ACPI_TYPE_STRING:
 164 
 165         ExternalObject->String.Pointer = (char *) DataSpace;
 166         ExternalObject->String.Length  = InternalObject->String.Length;
 167         *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD (
 168                             (ACPI_SIZE) InternalObject->String.Length + 1);
 169 
 170         ACPI_MEMCPY ((void *) DataSpace,
 171             (void *) InternalObject->String.Pointer,
 172             (ACPI_SIZE) InternalObject->String.Length + 1);
 173         break;
 174 
 175 
 176     case ACPI_TYPE_BUFFER:
 177 
 178         ExternalObject->Buffer.Pointer = DataSpace;
 179         ExternalObject->Buffer.Length  = InternalObject->Buffer.Length;
 180         *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD (
 181                             InternalObject->String.Length);
 182 
 183         ACPI_MEMCPY ((void *) DataSpace,
 184             (void *) InternalObject->Buffer.Pointer,
 185             InternalObject->Buffer.Length);
 186         break;
 187 
 188 
 189     case ACPI_TYPE_INTEGER:
 190 
 191         ExternalObject->Integer.Value = InternalObject->Integer.Value;
 192         break;
 193 
 194 
 195     case ACPI_TYPE_LOCAL_REFERENCE:
 196 
 197         /* This is an object reference. */
 198 
 199         switch (InternalObject->Reference.Class)
 200         {
 201         case ACPI_REFCLASS_NAME:
 202 
 203             /*
 204              * For namepath, return the object handle ("reference")
 205              * We are referring to the namespace node
 206              */
 207             ExternalObject->Reference.Handle =
 208                 InternalObject->Reference.Node;
 209             ExternalObject->Reference.ActualType =
 210                 AcpiNsGetType (InternalObject->Reference.Node);
 211             break;
 212 
 213         default:
 214 
 215             /* All other reference types are unsupported */
 216 
 217             return_ACPI_STATUS (AE_TYPE);
 218         }
 219         break;
 220 
 221 
 222     case ACPI_TYPE_PROCESSOR:
 223 
 224         ExternalObject->Processor.ProcId =
 225             InternalObject->Processor.ProcId;
 226         ExternalObject->Processor.PblkAddress =
 227             InternalObject->Processor.Address;
 228         ExternalObject->Processor.PblkLength =
 229             InternalObject->Processor.Length;
 230         break;
 231 
 232 
 233     case ACPI_TYPE_POWER:
 234 
 235         ExternalObject->PowerResource.SystemLevel =
 236             InternalObject->PowerResource.SystemLevel;
 237 
 238         ExternalObject->PowerResource.ResourceOrder =
 239             InternalObject->PowerResource.ResourceOrder;
 240         break;
 241 
 242 
 243     default:
 244         /*
 245          * There is no corresponding external object type
 246          */
 247         ACPI_ERROR ((AE_INFO,
 248             "Unsupported object type, cannot convert to external object: %s",
 249             AcpiUtGetTypeName (InternalObject->Common.Type)));
 250 
 251         return_ACPI_STATUS (AE_SUPPORT);
 252     }
 253 
 254     return_ACPI_STATUS (Status);
 255 }
 256 
 257 
 258 /*******************************************************************************
 259  *
 260  * FUNCTION:    AcpiUtCopyIelementToEelement
 261  *
 262  * PARAMETERS:  ACPI_PKG_CALLBACK
 263  *
 264  * RETURN:      Status
 265  *
 266  * DESCRIPTION: Copy one package element to another package element
 267  *
 268  ******************************************************************************/
 269 
 270 static ACPI_STATUS
 271 AcpiUtCopyIelementToEelement (
 272     UINT8                   ObjectType,
 273     ACPI_OPERAND_OBJECT     *SourceObject,
 274     ACPI_GENERIC_STATE      *State,
 275     void                    *Context)
 276 {
 277     ACPI_STATUS             Status = AE_OK;
 278     ACPI_PKG_INFO           *Info = (ACPI_PKG_INFO *) Context;
 279     ACPI_SIZE               ObjectSpace;
 280     UINT32                  ThisIndex;
 281     ACPI_OBJECT             *TargetObject;
 282 
 283 
 284     ACPI_FUNCTION_ENTRY ();
 285 
 286 
 287     ThisIndex    = State->Pkg.Index;
 288     TargetObject = (ACPI_OBJECT *)
 289         &((ACPI_OBJECT *)(State->Pkg.DestObject))->Package.Elements[ThisIndex];
 290 
 291     switch (ObjectType)
 292     {
 293     case ACPI_COPY_TYPE_SIMPLE:
 294 
 295         /*
 296          * This is a simple or null object
 297          */
 298         Status = AcpiUtCopyIsimpleToEsimple (SourceObject,
 299                         TargetObject, Info->FreeSpace, &ObjectSpace);
 300         if (ACPI_FAILURE (Status))
 301         {
 302             return (Status);
 303         }
 304         break;
 305 
 306 
 307     case ACPI_COPY_TYPE_PACKAGE:
 308 
 309         /*
 310          * Build the package object
 311          */
 312         TargetObject->Type              = ACPI_TYPE_PACKAGE;
 313         TargetObject->Package.Count     = SourceObject->Package.Count;
 314         TargetObject->Package.Elements  =
 315             ACPI_CAST_PTR (ACPI_OBJECT, Info->FreeSpace);
 316 
 317         /*
 318          * Pass the new package object back to the package walk routine
 319          */
 320         State->Pkg.ThisTargetObj = TargetObject;
 321 
 322         /*
 323          * Save space for the array of objects (Package elements)
 324          * update the buffer length counter
 325          */
 326         ObjectSpace = ACPI_ROUND_UP_TO_NATIVE_WORD (
 327                             (ACPI_SIZE) TargetObject->Package.Count *
 328                             sizeof (ACPI_OBJECT));
 329         break;
 330 
 331 
 332     default:
 333         return (AE_BAD_PARAMETER);
 334     }
 335 
 336     Info->FreeSpace   += ObjectSpace;
 337     Info->Length      += ObjectSpace;
 338     return (Status);
 339 }
 340 
 341 
 342 /*******************************************************************************
 343  *
 344  * FUNCTION:    AcpiUtCopyIpackageToEpackage
 345  *
 346  * PARAMETERS:  InternalObject      - Pointer to the object we are returning
 347  *              Buffer              - Where the object is returned
 348  *              SpaceUsed           - Where the object length is returned
 349  *
 350  * RETURN:      Status
 351  *
 352  * DESCRIPTION: This function is called to place a package object in a user
 353  *              buffer. A package object by definition contains other objects.
 354  *
 355  *              The buffer is assumed to have sufficient space for the object.
 356  *              The caller must have verified the buffer length needed using
 357  *              the AcpiUtGetObjectSize function before calling this function.
 358  *
 359  ******************************************************************************/
 360 
 361 static ACPI_STATUS
 362 AcpiUtCopyIpackageToEpackage (
 363     ACPI_OPERAND_OBJECT     *InternalObject,
 364     UINT8                   *Buffer,
 365     ACPI_SIZE               *SpaceUsed)
 366 {
 367     ACPI_OBJECT             *ExternalObject;
 368     ACPI_STATUS             Status;
 369     ACPI_PKG_INFO           Info;
 370 
 371 
 372     ACPI_FUNCTION_TRACE (UtCopyIpackageToEpackage);
 373 
 374 
 375     /*
 376      * First package at head of the buffer
 377      */
 378     ExternalObject = ACPI_CAST_PTR (ACPI_OBJECT, Buffer);
 379 
 380     /*
 381      * Free space begins right after the first package
 382      */
 383     Info.Length      = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
 384     Info.FreeSpace   = Buffer + ACPI_ROUND_UP_TO_NATIVE_WORD (
 385                                     sizeof (ACPI_OBJECT));
 386     Info.ObjectSpace = 0;
 387     Info.NumPackages = 1;
 388 
 389     ExternalObject->Type             = InternalObject->Common.Type;
 390     ExternalObject->Package.Count    = InternalObject->Package.Count;
 391     ExternalObject->Package.Elements = ACPI_CAST_PTR (ACPI_OBJECT,
 392                                             Info.FreeSpace);
 393 
 394     /*
 395      * Leave room for an array of ACPI_OBJECTS in the buffer
 396      * and move the free space past it
 397      */
 398     Info.Length    += (ACPI_SIZE) ExternalObject->Package.Count *
 399                             ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
 400     Info.FreeSpace += ExternalObject->Package.Count *
 401                             ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
 402 
 403     Status = AcpiUtWalkPackageTree (InternalObject, ExternalObject,
 404                 AcpiUtCopyIelementToEelement, &Info);
 405 
 406     *SpaceUsed = Info.Length;
 407     return_ACPI_STATUS (Status);
 408 }
 409 
 410 
 411 /*******************************************************************************
 412  *
 413  * FUNCTION:    AcpiUtCopyIobjectToEobject
 414  *
 415  * PARAMETERS:  InternalObject      - The internal object to be converted
 416  *              RetBuffer           - Where the object is returned
 417  *
 418  * RETURN:      Status
 419  *
 420  * DESCRIPTION: This function is called to build an API object to be returned
 421  *              to the caller.
 422  *
 423  ******************************************************************************/
 424 
 425 ACPI_STATUS
 426 AcpiUtCopyIobjectToEobject (
 427     ACPI_OPERAND_OBJECT     *InternalObject,
 428     ACPI_BUFFER             *RetBuffer)
 429 {
 430     ACPI_STATUS             Status;
 431 
 432 
 433     ACPI_FUNCTION_TRACE (UtCopyIobjectToEobject);
 434 
 435 
 436     if (InternalObject->Common.Type == ACPI_TYPE_PACKAGE)
 437     {
 438         /*
 439          * Package object:  Copy all subobjects (including
 440          * nested packages)
 441          */
 442         Status = AcpiUtCopyIpackageToEpackage (InternalObject,
 443                         RetBuffer->Pointer, &RetBuffer->Length);
 444     }
 445     else
 446     {
 447         /*
 448          * Build a simple object (no nested objects)
 449          */
 450         Status = AcpiUtCopyIsimpleToEsimple (InternalObject,
 451                     ACPI_CAST_PTR (ACPI_OBJECT, RetBuffer->Pointer),
 452                     ACPI_ADD_PTR (UINT8, RetBuffer->Pointer,
 453                         ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))),
 454                     &RetBuffer->Length);
 455         /*
 456          * build simple does not include the object size in the length
 457          * so we add it in here
 458          */
 459         RetBuffer->Length += sizeof (ACPI_OBJECT);
 460     }
 461 
 462     return_ACPI_STATUS (Status);
 463 }
 464 
 465 
 466 /*******************************************************************************
 467  *
 468  * FUNCTION:    AcpiUtCopyEsimpleToIsimple
 469  *
 470  * PARAMETERS:  ExternalObject      - The external object to be converted
 471  *              RetInternalObject   - Where the internal object is returned
 472  *
 473  * RETURN:      Status
 474  *
 475  * DESCRIPTION: This function copies an external object to an internal one.
 476  *              NOTE: Pointers can be copied, we don't need to copy data.
 477  *              (The pointers have to be valid in our address space no matter
 478  *              what we do with them!)
 479  *
 480  ******************************************************************************/
 481 
 482 static ACPI_STATUS
 483 AcpiUtCopyEsimpleToIsimple (
 484     ACPI_OBJECT             *ExternalObject,
 485     ACPI_OPERAND_OBJECT     **RetInternalObject)
 486 {
 487     ACPI_OPERAND_OBJECT     *InternalObject;
 488 
 489 
 490     ACPI_FUNCTION_TRACE (UtCopyEsimpleToIsimple);
 491 
 492 
 493     /*
 494      * Simple types supported are: String, Buffer, Integer
 495      */
 496     switch (ExternalObject->Type)
 497     {
 498     case ACPI_TYPE_STRING:
 499     case ACPI_TYPE_BUFFER:
 500     case ACPI_TYPE_INTEGER:
 501     case ACPI_TYPE_LOCAL_REFERENCE:
 502 
 503         InternalObject = AcpiUtCreateInternalObject (
 504                             (UINT8) ExternalObject->Type);
 505         if (!InternalObject)
 506         {
 507             return_ACPI_STATUS (AE_NO_MEMORY);
 508         }
 509         break;
 510 
 511     case ACPI_TYPE_ANY: /* This is the case for a NULL object */
 512 
 513         *RetInternalObject = NULL;
 514         return_ACPI_STATUS (AE_OK);
 515 
 516     default:
 517         /* All other types are not supported */
 518 
 519         ACPI_ERROR ((AE_INFO,
 520             "Unsupported object type, cannot convert to internal object: %s",
 521             AcpiUtGetTypeName (ExternalObject->Type)));
 522 
 523         return_ACPI_STATUS (AE_SUPPORT);
 524     }
 525 
 526 
 527     /* Must COPY string and buffer contents */
 528 
 529     switch (ExternalObject->Type)
 530     {
 531     case ACPI_TYPE_STRING:
 532 
 533         InternalObject->String.Pointer =
 534             ACPI_ALLOCATE_ZEROED ((ACPI_SIZE)
 535                 ExternalObject->String.Length + 1);
 536 
 537         if (!InternalObject->String.Pointer)
 538         {
 539             goto ErrorExit;
 540         }
 541 
 542         ACPI_MEMCPY (InternalObject->String.Pointer,
 543                      ExternalObject->String.Pointer,
 544                      ExternalObject->String.Length);
 545 
 546         InternalObject->String.Length  = ExternalObject->String.Length;
 547         break;
 548 
 549 
 550     case ACPI_TYPE_BUFFER:
 551 
 552         InternalObject->Buffer.Pointer =
 553             ACPI_ALLOCATE_ZEROED (ExternalObject->Buffer.Length);
 554         if (!InternalObject->Buffer.Pointer)
 555         {
 556             goto ErrorExit;
 557         }
 558 
 559         ACPI_MEMCPY (InternalObject->Buffer.Pointer,
 560                      ExternalObject->Buffer.Pointer,
 561                      ExternalObject->Buffer.Length);
 562 
 563         InternalObject->Buffer.Length  = ExternalObject->Buffer.Length;
 564 
 565         /* Mark buffer data valid */
 566 
 567         InternalObject->Buffer.Flags |= AOPOBJ_DATA_VALID;
 568         break;
 569 
 570 
 571     case ACPI_TYPE_INTEGER:
 572 
 573         InternalObject->Integer.Value   = ExternalObject->Integer.Value;
 574         break;
 575 
 576     case ACPI_TYPE_LOCAL_REFERENCE:
 577 
 578         /* TBD: should validate incoming handle */
 579 
 580         InternalObject->Reference.Class = ACPI_REFCLASS_NAME;
 581         InternalObject->Reference.Node = ExternalObject->Reference.Handle;
 582         break;
 583 
 584     default:
 585         /* Other types can't get here */
 586         break;
 587     }
 588 
 589     *RetInternalObject = InternalObject;
 590     return_ACPI_STATUS (AE_OK);
 591 
 592 
 593 ErrorExit:
 594     AcpiUtRemoveReference (InternalObject);
 595     return_ACPI_STATUS (AE_NO_MEMORY);
 596 }
 597 
 598 
 599 /*******************************************************************************
 600  *
 601  * FUNCTION:    AcpiUtCopyEpackageToIpackage
 602  *
 603  * PARAMETERS:  ExternalObject      - The external object to be converted
 604  *              InternalObject      - Where the internal object is returned
 605  *
 606  * RETURN:      Status
 607  *
 608  * DESCRIPTION: Copy an external package object to an internal package.
 609  *              Handles nested packages.
 610  *
 611  ******************************************************************************/
 612 
 613 static ACPI_STATUS
 614 AcpiUtCopyEpackageToIpackage (
 615     ACPI_OBJECT             *ExternalObject,
 616     ACPI_OPERAND_OBJECT     **InternalObject)
 617 {
 618     ACPI_STATUS             Status = AE_OK;
 619     ACPI_OPERAND_OBJECT     *PackageObject;
 620     ACPI_OPERAND_OBJECT     **PackageElements;
 621     UINT32                  i;
 622 
 623 
 624     ACPI_FUNCTION_TRACE (UtCopyEpackageToIpackage);
 625 
 626 
 627     /* Create the package object */
 628 
 629     PackageObject = AcpiUtCreatePackageObject (ExternalObject->Package.Count);
 630     if (!PackageObject)
 631     {
 632         return_ACPI_STATUS (AE_NO_MEMORY);
 633     }
 634 
 635     PackageElements = PackageObject->Package.Elements;
 636 
 637     /*
 638      * Recursive implementation. Probably ok, since nested external packages
 639      * as parameters should be very rare.
 640      */
 641     for (i = 0; i < ExternalObject->Package.Count; i++)
 642     {
 643         Status = AcpiUtCopyEobjectToIobject (
 644                     &ExternalObject->Package.Elements[i],
 645                     &PackageElements[i]);
 646         if (ACPI_FAILURE (Status))
 647         {
 648             /* Truncate package and delete it */
 649 
 650             PackageObject->Package.Count = i;
 651             PackageElements[i] = NULL;
 652             AcpiUtRemoveReference (PackageObject);
 653             return_ACPI_STATUS (Status);
 654         }
 655     }
 656 
 657     /* Mark package data valid */
 658 
 659     PackageObject->Package.Flags |= AOPOBJ_DATA_VALID;
 660 
 661     *InternalObject = PackageObject;
 662     return_ACPI_STATUS (Status);
 663 }
 664 
 665 
 666 /*******************************************************************************
 667  *
 668  * FUNCTION:    AcpiUtCopyEobjectToIobject
 669  *
 670  * PARAMETERS:  ExternalObject      - The external object to be converted
 671  *              InternalObject      - Where the internal object is returned
 672  *
 673  * RETURN:      Status
 674  *
 675  * DESCRIPTION: Converts an external object to an internal object.
 676  *
 677  ******************************************************************************/
 678 
 679 ACPI_STATUS
 680 AcpiUtCopyEobjectToIobject (
 681     ACPI_OBJECT             *ExternalObject,
 682     ACPI_OPERAND_OBJECT     **InternalObject)
 683 {
 684     ACPI_STATUS             Status;
 685 
 686 
 687     ACPI_FUNCTION_TRACE (UtCopyEobjectToIobject);
 688 
 689 
 690     if (ExternalObject->Type == ACPI_TYPE_PACKAGE)
 691     {
 692         Status = AcpiUtCopyEpackageToIpackage (ExternalObject, InternalObject);
 693     }
 694     else
 695     {
 696         /*
 697          * Build a simple object (no nested objects)
 698          */
 699         Status = AcpiUtCopyEsimpleToIsimple (ExternalObject, InternalObject);
 700     }
 701 
 702     return_ACPI_STATUS (Status);
 703 }
 704 
 705 
 706 /*******************************************************************************
 707  *
 708  * FUNCTION:    AcpiUtCopySimpleObject
 709  *
 710  * PARAMETERS:  SourceDesc          - The internal object to be copied
 711  *              DestDesc            - New target object
 712  *
 713  * RETURN:      Status
 714  *
 715  * DESCRIPTION: Simple copy of one internal object to another. Reference count
 716  *              of the destination object is preserved.
 717  *
 718  ******************************************************************************/
 719 
 720 static ACPI_STATUS
 721 AcpiUtCopySimpleObject (
 722     ACPI_OPERAND_OBJECT     *SourceDesc,
 723     ACPI_OPERAND_OBJECT     *DestDesc)
 724 {
 725     UINT16                  ReferenceCount;
 726     ACPI_OPERAND_OBJECT     *NextObject;
 727     ACPI_STATUS             Status;
 728     ACPI_SIZE               CopySize;
 729 
 730 
 731     /* Save fields from destination that we don't want to overwrite */
 732 
 733     ReferenceCount = DestDesc->Common.ReferenceCount;
 734     NextObject = DestDesc->Common.NextObject;
 735 
 736     /*
 737      * Copy the entire source object over the destination object.
 738      * Note: Source can be either an operand object or namespace node.
 739      */
 740     CopySize = sizeof (ACPI_OPERAND_OBJECT);
 741     if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
 742     {
 743         CopySize = sizeof (ACPI_NAMESPACE_NODE);
 744     }
 745 
 746     ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc),
 747         ACPI_CAST_PTR (char, SourceDesc), CopySize);
 748 
 749     /* Restore the saved fields */
 750 
 751     DestDesc->Common.ReferenceCount = ReferenceCount;
 752     DestDesc->Common.NextObject = NextObject;
 753 
 754     /* New object is not static, regardless of source */
 755 
 756     DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
 757 
 758     /* Handle the objects with extra data */
 759 
 760     switch (DestDesc->Common.Type)
 761     {
 762     case ACPI_TYPE_BUFFER:
 763         /*
 764          * Allocate and copy the actual buffer if and only if:
 765          * 1) There is a valid buffer pointer
 766          * 2) The buffer has a length > 0
 767          */
 768         if ((SourceDesc->Buffer.Pointer) &&
 769             (SourceDesc->Buffer.Length))
 770         {
 771             DestDesc->Buffer.Pointer =
 772                 ACPI_ALLOCATE (SourceDesc->Buffer.Length);
 773             if (!DestDesc->Buffer.Pointer)
 774             {
 775                 return (AE_NO_MEMORY);
 776             }
 777 
 778             /* Copy the actual buffer data */
 779 
 780             ACPI_MEMCPY (DestDesc->Buffer.Pointer,
 781                 SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length);
 782         }
 783         break;
 784 
 785     case ACPI_TYPE_STRING:
 786         /*
 787          * Allocate and copy the actual string if and only if:
 788          * 1) There is a valid string pointer
 789          * (Pointer to a NULL string is allowed)
 790          */
 791         if (SourceDesc->String.Pointer)
 792         {
 793             DestDesc->String.Pointer =
 794                 ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
 795             if (!DestDesc->String.Pointer)
 796             {
 797                 return (AE_NO_MEMORY);
 798             }
 799 
 800             /* Copy the actual string data */
 801 
 802             ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer,
 803                 (ACPI_SIZE) SourceDesc->String.Length + 1);
 804         }
 805         break;
 806 
 807     case ACPI_TYPE_LOCAL_REFERENCE:
 808         /*
 809          * We copied the reference object, so we now must add a reference
 810          * to the object pointed to by the reference
 811          *
 812          * DDBHandle reference (from Load/LoadTable) is a special reference,
 813          * it does not have a Reference.Object, so does not need to
 814          * increase the reference count
 815          */
 816         if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
 817         {
 818             break;
 819         }
 820 
 821         AcpiUtAddReference (SourceDesc->Reference.Object);
 822         break;
 823 
 824     case ACPI_TYPE_REGION:
 825         /*
 826          * We copied the Region Handler, so we now must add a reference
 827          */
 828         if (DestDesc->Region.Handler)
 829         {
 830             AcpiUtAddReference (DestDesc->Region.Handler);
 831         }
 832         break;
 833 
 834     /*
 835      * For Mutex and Event objects, we cannot simply copy the underlying
 836      * OS object. We must create a new one.
 837      */
 838     case ACPI_TYPE_MUTEX:
 839 
 840         Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex);
 841         if (ACPI_FAILURE (Status))
 842         {
 843             return (Status);
 844         }
 845         break;
 846 
 847     case ACPI_TYPE_EVENT:
 848 
 849         Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
 850                     &DestDesc->Event.OsSemaphore);
 851         if (ACPI_FAILURE (Status))
 852         {
 853             return (Status);
 854         }
 855         break;
 856 
 857     default:
 858         /* Nothing to do for other simple objects */
 859         break;
 860     }
 861 
 862     return (AE_OK);
 863 }
 864 
 865 
 866 /*******************************************************************************
 867  *
 868  * FUNCTION:    AcpiUtCopyIelementToIelement
 869  *
 870  * PARAMETERS:  ACPI_PKG_CALLBACK
 871  *
 872  * RETURN:      Status
 873  *
 874  * DESCRIPTION: Copy one package element to another package element
 875  *
 876  ******************************************************************************/
 877 
 878 static ACPI_STATUS
 879 AcpiUtCopyIelementToIelement (
 880     UINT8                   ObjectType,
 881     ACPI_OPERAND_OBJECT     *SourceObject,
 882     ACPI_GENERIC_STATE      *State,
 883     void                    *Context)
 884 {
 885     ACPI_STATUS             Status = AE_OK;
 886     UINT32                  ThisIndex;
 887     ACPI_OPERAND_OBJECT     **ThisTargetPtr;
 888     ACPI_OPERAND_OBJECT     *TargetObject;
 889 
 890 
 891     ACPI_FUNCTION_ENTRY ();
 892 
 893 
 894     ThisIndex     = State->Pkg.Index;
 895     ThisTargetPtr = (ACPI_OPERAND_OBJECT **)
 896                         &State->Pkg.DestObject->Package.Elements[ThisIndex];
 897 
 898     switch (ObjectType)
 899     {
 900     case ACPI_COPY_TYPE_SIMPLE:
 901 
 902         /* A null source object indicates a (legal) null package element */
 903 
 904         if (SourceObject)
 905         {
 906             /*
 907              * This is a simple object, just copy it
 908              */
 909             TargetObject = AcpiUtCreateInternalObject (
 910                                 SourceObject->Common.Type);
 911             if (!TargetObject)
 912             {
 913                 return (AE_NO_MEMORY);
 914             }
 915 
 916             Status = AcpiUtCopySimpleObject (SourceObject, TargetObject);
 917             if (ACPI_FAILURE (Status))
 918             {
 919                 goto ErrorExit;
 920             }
 921 
 922             *ThisTargetPtr = TargetObject;
 923         }
 924         else
 925         {
 926             /* Pass through a null element */
 927 
 928             *ThisTargetPtr = NULL;
 929         }
 930         break;
 931 
 932 
 933     case ACPI_COPY_TYPE_PACKAGE:
 934 
 935         /*
 936          * This object is a package - go down another nesting level
 937          * Create and build the package object
 938          */
 939         TargetObject = AcpiUtCreatePackageObject (SourceObject->Package.Count);
 940         if (!TargetObject)
 941         {
 942             return (AE_NO_MEMORY);
 943         }
 944 
 945         TargetObject->Common.Flags = SourceObject->Common.Flags;
 946 
 947         /* Pass the new package object back to the package walk routine */
 948 
 949         State->Pkg.ThisTargetObj = TargetObject;
 950 
 951         /* Store the object pointer in the parent package object */
 952 
 953         *ThisTargetPtr = TargetObject;
 954         break;
 955 
 956 
 957     default:
 958         return (AE_BAD_PARAMETER);
 959     }
 960 
 961     return (Status);
 962 
 963 ErrorExit:
 964     AcpiUtRemoveReference (TargetObject);
 965     return (Status);
 966 }
 967 
 968 
 969 /*******************************************************************************
 970  *
 971  * FUNCTION:    AcpiUtCopyIpackageToIpackage
 972  *
 973  * PARAMETERS:  SourceObj       - Pointer to the source package object
 974  *              DestObj         - Where the internal object is returned
 975  *              WalkState       - Current Walk state descriptor
 976  *
 977  * RETURN:      Status
 978  *
 979  * DESCRIPTION: This function is called to copy an internal package object
 980  *              into another internal package object.
 981  *
 982  ******************************************************************************/
 983 
 984 static ACPI_STATUS
 985 AcpiUtCopyIpackageToIpackage (
 986     ACPI_OPERAND_OBJECT     *SourceObj,
 987     ACPI_OPERAND_OBJECT     *DestObj,
 988     ACPI_WALK_STATE         *WalkState)
 989 {
 990     ACPI_STATUS             Status = AE_OK;
 991 
 992 
 993     ACPI_FUNCTION_TRACE (UtCopyIpackageToIpackage);
 994 
 995 
 996     DestObj->Common.Type    = SourceObj->Common.Type;
 997     DestObj->Common.Flags   = SourceObj->Common.Flags;
 998     DestObj->Package.Count  = SourceObj->Package.Count;
 999 
1000     /*
1001      * Create the object array and walk the source package tree
1002      */
1003     DestObj->Package.Elements = ACPI_ALLOCATE_ZEROED (
1004                                     ((ACPI_SIZE) SourceObj->Package.Count + 1) *
1005                                     sizeof (void *));
1006     if (!DestObj->Package.Elements)
1007     {
1008         ACPI_ERROR ((AE_INFO, "Package allocation failure"));
1009         return_ACPI_STATUS (AE_NO_MEMORY);
1010     }
1011 
1012     /*
1013      * Copy the package element-by-element by walking the package "tree".
1014      * This handles nested packages of arbitrary depth.
1015      */
1016     Status = AcpiUtWalkPackageTree (SourceObj, DestObj,
1017                 AcpiUtCopyIelementToIelement, WalkState);
1018     if (ACPI_FAILURE (Status))
1019     {
1020         /* On failure, delete the destination package object */
1021 
1022         AcpiUtRemoveReference (DestObj);
1023     }
1024 
1025     return_ACPI_STATUS (Status);
1026 }
1027 
1028 
1029 /*******************************************************************************
1030  *
1031  * FUNCTION:    AcpiUtCopyIobjectToIobject
1032  *
1033  * PARAMETERS:  SourceDesc          - The internal object to be copied
1034  *              DestDesc            - Where the copied object is returned
1035  *              WalkState           - Current walk state
1036  *
1037  * RETURN:      Status
1038  *
1039  * DESCRIPTION: Copy an internal object to a new internal object
1040  *
1041  ******************************************************************************/
1042 
1043 ACPI_STATUS
1044 AcpiUtCopyIobjectToIobject (
1045     ACPI_OPERAND_OBJECT     *SourceDesc,
1046     ACPI_OPERAND_OBJECT     **DestDesc,
1047     ACPI_WALK_STATE         *WalkState)
1048 {
1049     ACPI_STATUS             Status = AE_OK;
1050 
1051 
1052     ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject);
1053 
1054 
1055     /* Create the top level object */
1056 
1057     *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type);
1058     if (!*DestDesc)
1059     {
1060         return_ACPI_STATUS (AE_NO_MEMORY);
1061     }
1062 
1063     /* Copy the object and possible subobjects */
1064 
1065     if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE)
1066     {
1067         Status = AcpiUtCopyIpackageToIpackage (SourceDesc, *DestDesc,
1068                         WalkState);
1069     }
1070     else
1071     {
1072         Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc);
1073     }
1074 
1075     return_ACPI_STATUS (Status);
1076 }
1077 
1078