1 /******************************************************************************
   2  *
   3  * Module Name: utcopy - Internal to external object translation utilities
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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     case ACPI_TYPE_BUFFER:
 176 
 177         ExternalObject->Buffer.Pointer = DataSpace;
 178         ExternalObject->Buffer.Length  = InternalObject->Buffer.Length;
 179         *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD (
 180                             InternalObject->String.Length);
 181 
 182         ACPI_MEMCPY ((void *) DataSpace,
 183             (void *) InternalObject->Buffer.Pointer,
 184             InternalObject->Buffer.Length);
 185         break;
 186 
 187     case ACPI_TYPE_INTEGER:
 188 
 189         ExternalObject->Integer.Value = InternalObject->Integer.Value;
 190         break;
 191 
 192     case ACPI_TYPE_LOCAL_REFERENCE:
 193 
 194         /* This is an object reference. */
 195 
 196         switch (InternalObject->Reference.Class)
 197         {
 198         case ACPI_REFCLASS_NAME:
 199             /*
 200              * For namepath, return the object handle ("reference")
 201              * We are referring to the namespace node
 202              */
 203             ExternalObject->Reference.Handle =
 204                 InternalObject->Reference.Node;
 205             ExternalObject->Reference.ActualType =
 206                 AcpiNsGetType (InternalObject->Reference.Node);
 207             break;
 208 
 209         default:
 210 
 211             /* All other reference types are unsupported */
 212 
 213             return_ACPI_STATUS (AE_TYPE);
 214         }
 215         break;
 216 
 217     case ACPI_TYPE_PROCESSOR:
 218 
 219         ExternalObject->Processor.ProcId =
 220             InternalObject->Processor.ProcId;
 221         ExternalObject->Processor.PblkAddress =
 222             InternalObject->Processor.Address;
 223         ExternalObject->Processor.PblkLength =
 224             InternalObject->Processor.Length;
 225         break;
 226 
 227     case ACPI_TYPE_POWER:
 228 
 229         ExternalObject->PowerResource.SystemLevel =
 230             InternalObject->PowerResource.SystemLevel;
 231 
 232         ExternalObject->PowerResource.ResourceOrder =
 233             InternalObject->PowerResource.ResourceOrder;
 234         break;
 235 
 236     default:
 237         /*
 238          * There is no corresponding external object type
 239          */
 240         ACPI_ERROR ((AE_INFO,
 241             "Unsupported object type, cannot convert to external object: %s",
 242             AcpiUtGetTypeName (InternalObject->Common.Type)));
 243 
 244         return_ACPI_STATUS (AE_SUPPORT);
 245     }
 246 
 247     return_ACPI_STATUS (Status);
 248 }
 249 
 250 
 251 /*******************************************************************************
 252  *
 253  * FUNCTION:    AcpiUtCopyIelementToEelement
 254  *
 255  * PARAMETERS:  ACPI_PKG_CALLBACK
 256  *
 257  * RETURN:      Status
 258  *
 259  * DESCRIPTION: Copy one package element to another package element
 260  *
 261  ******************************************************************************/
 262 
 263 static ACPI_STATUS
 264 AcpiUtCopyIelementToEelement (
 265     UINT8                   ObjectType,
 266     ACPI_OPERAND_OBJECT     *SourceObject,
 267     ACPI_GENERIC_STATE      *State,
 268     void                    *Context)
 269 {
 270     ACPI_STATUS             Status = AE_OK;
 271     ACPI_PKG_INFO           *Info = (ACPI_PKG_INFO *) Context;
 272     ACPI_SIZE               ObjectSpace;
 273     UINT32                  ThisIndex;
 274     ACPI_OBJECT             *TargetObject;
 275 
 276 
 277     ACPI_FUNCTION_ENTRY ();
 278 
 279 
 280     ThisIndex    = State->Pkg.Index;
 281     TargetObject = (ACPI_OBJECT *)
 282         &((ACPI_OBJECT *)(State->Pkg.DestObject))->Package.Elements[ThisIndex];
 283 
 284     switch (ObjectType)
 285     {
 286     case ACPI_COPY_TYPE_SIMPLE:
 287         /*
 288          * This is a simple or null object
 289          */
 290         Status = AcpiUtCopyIsimpleToEsimple (SourceObject,
 291                         TargetObject, Info->FreeSpace, &ObjectSpace);
 292         if (ACPI_FAILURE (Status))
 293         {
 294             return (Status);
 295         }
 296         break;
 297 
 298     case ACPI_COPY_TYPE_PACKAGE:
 299         /*
 300          * Build the package object
 301          */
 302         TargetObject->Type              = ACPI_TYPE_PACKAGE;
 303         TargetObject->Package.Count     = SourceObject->Package.Count;
 304         TargetObject->Package.Elements  =
 305             ACPI_CAST_PTR (ACPI_OBJECT, Info->FreeSpace);
 306 
 307         /*
 308          * Pass the new package object back to the package walk routine
 309          */
 310         State->Pkg.ThisTargetObj = TargetObject;
 311 
 312         /*
 313          * Save space for the array of objects (Package elements)
 314          * update the buffer length counter
 315          */
 316         ObjectSpace = ACPI_ROUND_UP_TO_NATIVE_WORD (
 317                             (ACPI_SIZE) TargetObject->Package.Count *
 318                             sizeof (ACPI_OBJECT));
 319         break;
 320 
 321     default:
 322 
 323         return (AE_BAD_PARAMETER);
 324     }
 325 
 326     Info->FreeSpace   += ObjectSpace;
 327     Info->Length      += ObjectSpace;
 328     return (Status);
 329 }
 330 
 331 
 332 /*******************************************************************************
 333  *
 334  * FUNCTION:    AcpiUtCopyIpackageToEpackage
 335  *
 336  * PARAMETERS:  InternalObject      - Pointer to the object we are returning
 337  *              Buffer              - Where the object is returned
 338  *              SpaceUsed           - Where the object length is returned
 339  *
 340  * RETURN:      Status
 341  *
 342  * DESCRIPTION: This function is called to place a package object in a user
 343  *              buffer. A package object by definition contains other objects.
 344  *
 345  *              The buffer is assumed to have sufficient space for the object.
 346  *              The caller must have verified the buffer length needed using
 347  *              the AcpiUtGetObjectSize function before calling this function.
 348  *
 349  ******************************************************************************/
 350 
 351 static ACPI_STATUS
 352 AcpiUtCopyIpackageToEpackage (
 353     ACPI_OPERAND_OBJECT     *InternalObject,
 354     UINT8                   *Buffer,
 355     ACPI_SIZE               *SpaceUsed)
 356 {
 357     ACPI_OBJECT             *ExternalObject;
 358     ACPI_STATUS             Status;
 359     ACPI_PKG_INFO           Info;
 360 
 361 
 362     ACPI_FUNCTION_TRACE (UtCopyIpackageToEpackage);
 363 
 364 
 365     /*
 366      * First package at head of the buffer
 367      */
 368     ExternalObject = ACPI_CAST_PTR (ACPI_OBJECT, Buffer);
 369 
 370     /*
 371      * Free space begins right after the first package
 372      */
 373     Info.Length      = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
 374     Info.FreeSpace   = Buffer + ACPI_ROUND_UP_TO_NATIVE_WORD (
 375                                     sizeof (ACPI_OBJECT));
 376     Info.ObjectSpace = 0;
 377     Info.NumPackages = 1;
 378 
 379     ExternalObject->Type             = InternalObject->Common.Type;
 380     ExternalObject->Package.Count    = InternalObject->Package.Count;
 381     ExternalObject->Package.Elements = ACPI_CAST_PTR (ACPI_OBJECT,
 382                                             Info.FreeSpace);
 383 
 384     /*
 385      * Leave room for an array of ACPI_OBJECTS in the buffer
 386      * and move the free space past it
 387      */
 388     Info.Length    += (ACPI_SIZE) ExternalObject->Package.Count *
 389                             ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
 390     Info.FreeSpace += ExternalObject->Package.Count *
 391                             ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
 392 
 393     Status = AcpiUtWalkPackageTree (InternalObject, ExternalObject,
 394                 AcpiUtCopyIelementToEelement, &Info);
 395 
 396     *SpaceUsed = Info.Length;
 397     return_ACPI_STATUS (Status);
 398 }
 399 
 400 
 401 /*******************************************************************************
 402  *
 403  * FUNCTION:    AcpiUtCopyIobjectToEobject
 404  *
 405  * PARAMETERS:  InternalObject      - The internal object to be converted
 406  *              RetBuffer           - Where the object is returned
 407  *
 408  * RETURN:      Status
 409  *
 410  * DESCRIPTION: This function is called to build an API object to be returned
 411  *              to the caller.
 412  *
 413  ******************************************************************************/
 414 
 415 ACPI_STATUS
 416 AcpiUtCopyIobjectToEobject (
 417     ACPI_OPERAND_OBJECT     *InternalObject,
 418     ACPI_BUFFER             *RetBuffer)
 419 {
 420     ACPI_STATUS             Status;
 421 
 422 
 423     ACPI_FUNCTION_TRACE (UtCopyIobjectToEobject);
 424 
 425 
 426     if (InternalObject->Common.Type == ACPI_TYPE_PACKAGE)
 427     {
 428         /*
 429          * Package object:  Copy all subobjects (including
 430          * nested packages)
 431          */
 432         Status = AcpiUtCopyIpackageToEpackage (InternalObject,
 433                         RetBuffer->Pointer, &RetBuffer->Length);
 434     }
 435     else
 436     {
 437         /*
 438          * Build a simple object (no nested objects)
 439          */
 440         Status = AcpiUtCopyIsimpleToEsimple (InternalObject,
 441                     ACPI_CAST_PTR (ACPI_OBJECT, RetBuffer->Pointer),
 442                     ACPI_ADD_PTR (UINT8, RetBuffer->Pointer,
 443                         ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))),
 444                     &RetBuffer->Length);
 445         /*
 446          * build simple does not include the object size in the length
 447          * so we add it in here
 448          */
 449         RetBuffer->Length += sizeof (ACPI_OBJECT);
 450     }
 451 
 452     return_ACPI_STATUS (Status);
 453 }
 454 
 455 
 456 /*******************************************************************************
 457  *
 458  * FUNCTION:    AcpiUtCopyEsimpleToIsimple
 459  *
 460  * PARAMETERS:  ExternalObject      - The external object to be converted
 461  *              RetInternalObject   - Where the internal object is returned
 462  *
 463  * RETURN:      Status
 464  *
 465  * DESCRIPTION: This function copies an external object to an internal one.
 466  *              NOTE: Pointers can be copied, we don't need to copy data.
 467  *              (The pointers have to be valid in our address space no matter
 468  *              what we do with them!)
 469  *
 470  ******************************************************************************/
 471 
 472 static ACPI_STATUS
 473 AcpiUtCopyEsimpleToIsimple (
 474     ACPI_OBJECT             *ExternalObject,
 475     ACPI_OPERAND_OBJECT     **RetInternalObject)
 476 {
 477     ACPI_OPERAND_OBJECT     *InternalObject;
 478 
 479 
 480     ACPI_FUNCTION_TRACE (UtCopyEsimpleToIsimple);
 481 
 482 
 483     /*
 484      * Simple types supported are: String, Buffer, Integer
 485      */
 486     switch (ExternalObject->Type)
 487     {
 488     case ACPI_TYPE_STRING:
 489     case ACPI_TYPE_BUFFER:
 490     case ACPI_TYPE_INTEGER:
 491     case ACPI_TYPE_LOCAL_REFERENCE:
 492 
 493         InternalObject = AcpiUtCreateInternalObject (
 494                             (UINT8) ExternalObject->Type);
 495         if (!InternalObject)
 496         {
 497             return_ACPI_STATUS (AE_NO_MEMORY);
 498         }
 499         break;
 500 
 501     case ACPI_TYPE_ANY: /* This is the case for a NULL object */
 502 
 503         *RetInternalObject = NULL;
 504         return_ACPI_STATUS (AE_OK);
 505 
 506     default:
 507 
 508         /* All other types are not supported */
 509 
 510         ACPI_ERROR ((AE_INFO,
 511             "Unsupported object type, cannot convert to internal object: %s",
 512             AcpiUtGetTypeName (ExternalObject->Type)));
 513 
 514         return_ACPI_STATUS (AE_SUPPORT);
 515     }
 516 
 517 
 518     /* Must COPY string and buffer contents */
 519 
 520     switch (ExternalObject->Type)
 521     {
 522     case ACPI_TYPE_STRING:
 523 
 524         InternalObject->String.Pointer =
 525             ACPI_ALLOCATE_ZEROED ((ACPI_SIZE)
 526                 ExternalObject->String.Length + 1);
 527 
 528         if (!InternalObject->String.Pointer)
 529         {
 530             goto ErrorExit;
 531         }
 532 
 533         ACPI_MEMCPY (InternalObject->String.Pointer,
 534                      ExternalObject->String.Pointer,
 535                      ExternalObject->String.Length);
 536 
 537         InternalObject->String.Length  = ExternalObject->String.Length;
 538         break;
 539 
 540     case ACPI_TYPE_BUFFER:
 541 
 542         InternalObject->Buffer.Pointer =
 543             ACPI_ALLOCATE_ZEROED (ExternalObject->Buffer.Length);
 544         if (!InternalObject->Buffer.Pointer)
 545         {
 546             goto ErrorExit;
 547         }
 548 
 549         ACPI_MEMCPY (InternalObject->Buffer.Pointer,
 550                      ExternalObject->Buffer.Pointer,
 551                      ExternalObject->Buffer.Length);
 552 
 553         InternalObject->Buffer.Length  = ExternalObject->Buffer.Length;
 554 
 555         /* Mark buffer data valid */
 556 
 557         InternalObject->Buffer.Flags |= AOPOBJ_DATA_VALID;
 558         break;
 559 
 560     case ACPI_TYPE_INTEGER:
 561 
 562         InternalObject->Integer.Value   = ExternalObject->Integer.Value;
 563         break;
 564 
 565     case ACPI_TYPE_LOCAL_REFERENCE:
 566 
 567         /* An incoming reference is defined to be a namespace node */
 568 
 569         InternalObject->Reference.Class = ACPI_REFCLASS_REFOF;
 570         InternalObject->Reference.Object = ExternalObject->Reference.Handle;
 571         break;
 572 
 573     default:
 574 
 575         /* Other types can't get here */
 576 
 577         break;
 578     }
 579 
 580     *RetInternalObject = InternalObject;
 581     return_ACPI_STATUS (AE_OK);
 582 
 583 
 584 ErrorExit:
 585     AcpiUtRemoveReference (InternalObject);
 586     return_ACPI_STATUS (AE_NO_MEMORY);
 587 }
 588 
 589 
 590 /*******************************************************************************
 591  *
 592  * FUNCTION:    AcpiUtCopyEpackageToIpackage
 593  *
 594  * PARAMETERS:  ExternalObject      - The external object to be converted
 595  *              InternalObject      - Where the internal object is returned
 596  *
 597  * RETURN:      Status
 598  *
 599  * DESCRIPTION: Copy an external package object to an internal package.
 600  *              Handles nested packages.
 601  *
 602  ******************************************************************************/
 603 
 604 static ACPI_STATUS
 605 AcpiUtCopyEpackageToIpackage (
 606     ACPI_OBJECT             *ExternalObject,
 607     ACPI_OPERAND_OBJECT     **InternalObject)
 608 {
 609     ACPI_STATUS             Status = AE_OK;
 610     ACPI_OPERAND_OBJECT     *PackageObject;
 611     ACPI_OPERAND_OBJECT     **PackageElements;
 612     UINT32                  i;
 613 
 614 
 615     ACPI_FUNCTION_TRACE (UtCopyEpackageToIpackage);
 616 
 617 
 618     /* Create the package object */
 619 
 620     PackageObject = AcpiUtCreatePackageObject (ExternalObject->Package.Count);
 621     if (!PackageObject)
 622     {
 623         return_ACPI_STATUS (AE_NO_MEMORY);
 624     }
 625 
 626     PackageElements = PackageObject->Package.Elements;
 627 
 628     /*
 629      * Recursive implementation. Probably ok, since nested external packages
 630      * as parameters should be very rare.
 631      */
 632     for (i = 0; i < ExternalObject->Package.Count; i++)
 633     {
 634         Status = AcpiUtCopyEobjectToIobject (
 635                     &ExternalObject->Package.Elements[i],
 636                     &PackageElements[i]);
 637         if (ACPI_FAILURE (Status))
 638         {
 639             /* Truncate package and delete it */
 640 
 641             PackageObject->Package.Count = i;
 642             PackageElements[i] = NULL;
 643             AcpiUtRemoveReference (PackageObject);
 644             return_ACPI_STATUS (Status);
 645         }
 646     }
 647 
 648     /* Mark package data valid */
 649 
 650     PackageObject->Package.Flags |= AOPOBJ_DATA_VALID;
 651 
 652     *InternalObject = PackageObject;
 653     return_ACPI_STATUS (Status);
 654 }
 655 
 656 
 657 /*******************************************************************************
 658  *
 659  * FUNCTION:    AcpiUtCopyEobjectToIobject
 660  *
 661  * PARAMETERS:  ExternalObject      - The external object to be converted
 662  *              InternalObject      - Where the internal object is returned
 663  *
 664  * RETURN:      Status
 665  *
 666  * DESCRIPTION: Converts an external object to an internal object.
 667  *
 668  ******************************************************************************/
 669 
 670 ACPI_STATUS
 671 AcpiUtCopyEobjectToIobject (
 672     ACPI_OBJECT             *ExternalObject,
 673     ACPI_OPERAND_OBJECT     **InternalObject)
 674 {
 675     ACPI_STATUS             Status;
 676 
 677 
 678     ACPI_FUNCTION_TRACE (UtCopyEobjectToIobject);
 679 
 680 
 681     if (ExternalObject->Type == ACPI_TYPE_PACKAGE)
 682     {
 683         Status = AcpiUtCopyEpackageToIpackage (ExternalObject, InternalObject);
 684     }
 685     else
 686     {
 687         /*
 688          * Build a simple object (no nested objects)
 689          */
 690         Status = AcpiUtCopyEsimpleToIsimple (ExternalObject, InternalObject);
 691     }
 692 
 693     return_ACPI_STATUS (Status);
 694 }
 695 
 696 
 697 /*******************************************************************************
 698  *
 699  * FUNCTION:    AcpiUtCopySimpleObject
 700  *
 701  * PARAMETERS:  SourceDesc          - The internal object to be copied
 702  *              DestDesc            - New target object
 703  *
 704  * RETURN:      Status
 705  *
 706  * DESCRIPTION: Simple copy of one internal object to another. Reference count
 707  *              of the destination object is preserved.
 708  *
 709  ******************************************************************************/
 710 
 711 static ACPI_STATUS
 712 AcpiUtCopySimpleObject (
 713     ACPI_OPERAND_OBJECT     *SourceDesc,
 714     ACPI_OPERAND_OBJECT     *DestDesc)
 715 {
 716     UINT16                  ReferenceCount;
 717     ACPI_OPERAND_OBJECT     *NextObject;
 718     ACPI_STATUS             Status;
 719     ACPI_SIZE               CopySize;
 720 
 721 
 722     /* Save fields from destination that we don't want to overwrite */
 723 
 724     ReferenceCount = DestDesc->Common.ReferenceCount;
 725     NextObject = DestDesc->Common.NextObject;
 726 
 727     /*
 728      * Copy the entire source object over the destination object.
 729      * Note: Source can be either an operand object or namespace node.
 730      */
 731     CopySize = sizeof (ACPI_OPERAND_OBJECT);
 732     if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
 733     {
 734         CopySize = sizeof (ACPI_NAMESPACE_NODE);
 735     }
 736 
 737     ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc),
 738         ACPI_CAST_PTR (char, SourceDesc), CopySize);
 739 
 740     /* Restore the saved fields */
 741 
 742     DestDesc->Common.ReferenceCount = ReferenceCount;
 743     DestDesc->Common.NextObject = NextObject;
 744 
 745     /* New object is not static, regardless of source */
 746 
 747     DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
 748 
 749     /* Handle the objects with extra data */
 750 
 751     switch (DestDesc->Common.Type)
 752     {
 753     case ACPI_TYPE_BUFFER:
 754         /*
 755          * Allocate and copy the actual buffer if and only if:
 756          * 1) There is a valid buffer pointer
 757          * 2) The buffer has a length > 0
 758          */
 759         if ((SourceDesc->Buffer.Pointer) &&
 760             (SourceDesc->Buffer.Length))
 761         {
 762             DestDesc->Buffer.Pointer =
 763                 ACPI_ALLOCATE (SourceDesc->Buffer.Length);
 764             if (!DestDesc->Buffer.Pointer)
 765             {
 766                 return (AE_NO_MEMORY);
 767             }
 768 
 769             /* Copy the actual buffer data */
 770 
 771             ACPI_MEMCPY (DestDesc->Buffer.Pointer,
 772                 SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length);
 773         }
 774         break;
 775 
 776     case ACPI_TYPE_STRING:
 777         /*
 778          * Allocate and copy the actual string if and only if:
 779          * 1) There is a valid string pointer
 780          * (Pointer to a NULL string is allowed)
 781          */
 782         if (SourceDesc->String.Pointer)
 783         {
 784             DestDesc->String.Pointer =
 785                 ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
 786             if (!DestDesc->String.Pointer)
 787             {
 788                 return (AE_NO_MEMORY);
 789             }
 790 
 791             /* Copy the actual string data */
 792 
 793             ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer,
 794                 (ACPI_SIZE) SourceDesc->String.Length + 1);
 795         }
 796         break;
 797 
 798     case ACPI_TYPE_LOCAL_REFERENCE:
 799         /*
 800          * We copied the reference object, so we now must add a reference
 801          * to the object pointed to by the reference
 802          *
 803          * DDBHandle reference (from Load/LoadTable) is a special reference,
 804          * it does not have a Reference.Object, so does not need to
 805          * increase the reference count
 806          */
 807         if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
 808         {
 809             break;
 810         }
 811 
 812         AcpiUtAddReference (SourceDesc->Reference.Object);
 813         break;
 814 
 815     case ACPI_TYPE_REGION:
 816         /*
 817          * We copied the Region Handler, so we now must add a reference
 818          */
 819         if (DestDesc->Region.Handler)
 820         {
 821             AcpiUtAddReference (DestDesc->Region.Handler);
 822         }
 823         break;
 824 
 825     /*
 826      * For Mutex and Event objects, we cannot simply copy the underlying
 827      * OS object. We must create a new one.
 828      */
 829     case ACPI_TYPE_MUTEX:
 830 
 831         Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex);
 832         if (ACPI_FAILURE (Status))
 833         {
 834             return (Status);
 835         }
 836         break;
 837 
 838     case ACPI_TYPE_EVENT:
 839 
 840         Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
 841                     &DestDesc->Event.OsSemaphore);
 842         if (ACPI_FAILURE (Status))
 843         {
 844             return (Status);
 845         }
 846         break;
 847 
 848     default:
 849 
 850         /* Nothing to do for other simple objects */
 851 
 852         break;
 853     }
 854 
 855     return (AE_OK);
 856 }
 857 
 858 
 859 /*******************************************************************************
 860  *
 861  * FUNCTION:    AcpiUtCopyIelementToIelement
 862  *
 863  * PARAMETERS:  ACPI_PKG_CALLBACK
 864  *
 865  * RETURN:      Status
 866  *
 867  * DESCRIPTION: Copy one package element to another package element
 868  *
 869  ******************************************************************************/
 870 
 871 static ACPI_STATUS
 872 AcpiUtCopyIelementToIelement (
 873     UINT8                   ObjectType,
 874     ACPI_OPERAND_OBJECT     *SourceObject,
 875     ACPI_GENERIC_STATE      *State,
 876     void                    *Context)
 877 {
 878     ACPI_STATUS             Status = AE_OK;
 879     UINT32                  ThisIndex;
 880     ACPI_OPERAND_OBJECT     **ThisTargetPtr;
 881     ACPI_OPERAND_OBJECT     *TargetObject;
 882 
 883 
 884     ACPI_FUNCTION_ENTRY ();
 885 
 886 
 887     ThisIndex     = State->Pkg.Index;
 888     ThisTargetPtr = (ACPI_OPERAND_OBJECT **)
 889                         &State->Pkg.DestObject->Package.Elements[ThisIndex];
 890 
 891     switch (ObjectType)
 892     {
 893     case ACPI_COPY_TYPE_SIMPLE:
 894 
 895         /* A null source object indicates a (legal) null package element */
 896 
 897         if (SourceObject)
 898         {
 899             /*
 900              * This is a simple object, just copy it
 901              */
 902             TargetObject = AcpiUtCreateInternalObject (
 903                                 SourceObject->Common.Type);
 904             if (!TargetObject)
 905             {
 906                 return (AE_NO_MEMORY);
 907             }
 908 
 909             Status = AcpiUtCopySimpleObject (SourceObject, TargetObject);
 910             if (ACPI_FAILURE (Status))
 911             {
 912                 goto ErrorExit;
 913             }
 914 
 915             *ThisTargetPtr = TargetObject;
 916         }
 917         else
 918         {
 919             /* Pass through a null element */
 920 
 921             *ThisTargetPtr = NULL;
 922         }
 923         break;
 924 
 925     case ACPI_COPY_TYPE_PACKAGE:
 926         /*
 927          * This object is a package - go down another nesting level
 928          * Create and build the package object
 929          */
 930         TargetObject = AcpiUtCreatePackageObject (SourceObject->Package.Count);
 931         if (!TargetObject)
 932         {
 933             return (AE_NO_MEMORY);
 934         }
 935 
 936         TargetObject->Common.Flags = SourceObject->Common.Flags;
 937 
 938         /* Pass the new package object back to the package walk routine */
 939 
 940         State->Pkg.ThisTargetObj = TargetObject;
 941 
 942         /* Store the object pointer in the parent package object */
 943 
 944         *ThisTargetPtr = TargetObject;
 945         break;
 946 
 947     default:
 948 
 949         return (AE_BAD_PARAMETER);
 950     }
 951 
 952     return (Status);
 953 
 954 ErrorExit:
 955     AcpiUtRemoveReference (TargetObject);
 956     return (Status);
 957 }
 958 
 959 
 960 /*******************************************************************************
 961  *
 962  * FUNCTION:    AcpiUtCopyIpackageToIpackage
 963  *
 964  * PARAMETERS:  SourceObj       - Pointer to the source package object
 965  *              DestObj         - Where the internal object is returned
 966  *              WalkState       - Current Walk state descriptor
 967  *
 968  * RETURN:      Status
 969  *
 970  * DESCRIPTION: This function is called to copy an internal package object
 971  *              into another internal package object.
 972  *
 973  ******************************************************************************/
 974 
 975 static ACPI_STATUS
 976 AcpiUtCopyIpackageToIpackage (
 977     ACPI_OPERAND_OBJECT     *SourceObj,
 978     ACPI_OPERAND_OBJECT     *DestObj,
 979     ACPI_WALK_STATE         *WalkState)
 980 {
 981     ACPI_STATUS             Status = AE_OK;
 982 
 983 
 984     ACPI_FUNCTION_TRACE (UtCopyIpackageToIpackage);
 985 
 986 
 987     DestObj->Common.Type    = SourceObj->Common.Type;
 988     DestObj->Common.Flags   = SourceObj->Common.Flags;
 989     DestObj->Package.Count  = SourceObj->Package.Count;
 990 
 991     /*
 992      * Create the object array and walk the source package tree
 993      */
 994     DestObj->Package.Elements = ACPI_ALLOCATE_ZEROED (
 995                                     ((ACPI_SIZE) SourceObj->Package.Count + 1) *
 996                                     sizeof (void *));
 997     if (!DestObj->Package.Elements)
 998     {
 999         ACPI_ERROR ((AE_INFO, "Package allocation failure"));
1000         return_ACPI_STATUS (AE_NO_MEMORY);
1001     }
1002 
1003     /*
1004      * Copy the package element-by-element by walking the package "tree".
1005      * This handles nested packages of arbitrary depth.
1006      */
1007     Status = AcpiUtWalkPackageTree (SourceObj, DestObj,
1008                 AcpiUtCopyIelementToIelement, WalkState);
1009     if (ACPI_FAILURE (Status))
1010     {
1011         /* On failure, delete the destination package object */
1012 
1013         AcpiUtRemoveReference (DestObj);
1014     }
1015 
1016     return_ACPI_STATUS (Status);
1017 }
1018 
1019 
1020 /*******************************************************************************
1021  *
1022  * FUNCTION:    AcpiUtCopyIobjectToIobject
1023  *
1024  * PARAMETERS:  SourceDesc          - The internal object to be copied
1025  *              DestDesc            - Where the copied object is returned
1026  *              WalkState           - Current walk state
1027  *
1028  * RETURN:      Status
1029  *
1030  * DESCRIPTION: Copy an internal object to a new internal object
1031  *
1032  ******************************************************************************/
1033 
1034 ACPI_STATUS
1035 AcpiUtCopyIobjectToIobject (
1036     ACPI_OPERAND_OBJECT     *SourceDesc,
1037     ACPI_OPERAND_OBJECT     **DestDesc,
1038     ACPI_WALK_STATE         *WalkState)
1039 {
1040     ACPI_STATUS             Status = AE_OK;
1041 
1042 
1043     ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject);
1044 
1045 
1046     /* Create the top level object */
1047 
1048     *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type);
1049     if (!*DestDesc)
1050     {
1051         return_ACPI_STATUS (AE_NO_MEMORY);
1052     }
1053 
1054     /* Copy the object and possible subobjects */
1055 
1056     if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE)
1057     {
1058         Status = AcpiUtCopyIpackageToIpackage (SourceDesc, *DestDesc,
1059                         WalkState);
1060     }
1061     else
1062     {
1063         Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc);
1064     }
1065 
1066     return_ACPI_STATUS (Status);
1067 }