exstore.c revision 70243
12786Ssos
22786Ssos/******************************************************************************
32786Ssos *
42786Ssos * Module Name: amstore - AML Interpreter object store support
52786Ssos *              $Revision: 118 $
62786Ssos *
72786Ssos *****************************************************************************/
82786Ssos
92786Ssos/******************************************************************************
102786Ssos *
112786Ssos * 1. Copyright Notice
122786Ssos *
132786Ssos * Some or all of this work - Copyright (c) 1999, 2000, Intel Corp.
142786Ssos * All rights reserved.
152786Ssos *
162786Ssos * 2. License
172786Ssos *
182786Ssos * 2.1. This is your license from Intel Corp. under its intellectual property
192786Ssos * rights.  You may have additional license terms from the party that provided
202786Ssos * you this software, covering your right to use that party's intellectual
212786Ssos * property rights.
222786Ssos *
232786Ssos * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
242786Ssos * copy of the source code appearing in this file ("Covered Code") an
252786Ssos * irrevocable, perpetual, worldwide license under Intel's copyrights in the
262786Ssos * base code distributed originally by Intel ("Original Intel Code") to copy,
272786Ssos * make derivatives, distribute, use and display any portion of the Covered
282786Ssos * Code in any form, with the right to sublicense such rights; and
292786Ssos *
302786Ssos * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
312786Ssos * license (with the right to sublicense), under only those claims of Intel
322786Ssos * patents that are infringed by the Original Intel Code, to make, use, sell,
332786Ssos * offer to sell, and import the Covered Code and derivative works thereof
342786Ssos * solely to the minimum extent necessary to exercise the above copyright
352786Ssos * license, and in no event shall the patent license extend to any additions
362786Ssos * to or modifications of the Original Intel Code.  No other license or right
372786Ssos * is granted directly or by implication, estoppel or otherwise;
382786Ssos *
392786Ssos * The above copyright and patent license is granted only if the following
402786Ssos * conditions are met:
412786Ssos *
422786Ssos * 3. Conditions
432786Ssos *
442786Ssos * 3.1. Redistribution of Source with Rights to Further Distribute Source.
452786Ssos * Redistribution of source code of any substantial portion of the Covered
462786Ssos * Code or modification with rights to further distribute source must include
472786Ssos * the above Copyright Notice, the above License, this list of Conditions,
482786Ssos * and the following Disclaimer and Export Compliance provision.  In addition,
492786Ssos * Licensee must cause all Covered Code to which Licensee contributes to
502786Ssos * contain a file documenting the changes Licensee made to create that Covered
512786Ssos * Code and the date of any change.  Licensee must include in that file the
522786Ssos * documentation of any changes made by any predecessor Licensee.  Licensee
532786Ssos * must include a prominent statement that the modification is derived,
542786Ssos * directly or indirectly, from Original Intel Code.
552786Ssos *
562786Ssos * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
572786Ssos * Redistribution of source code of any substantial portion of the Covered
582786Ssos * Code or modification without rights to further distribute source must
592786Ssos * include the following Disclaimer and Export Compliance provision in the
602786Ssos * documentation and/or other materials provided with distribution.  In
612786Ssos * addition, Licensee may not authorize further sublicense of source of any
622786Ssos * portion of the Covered Code, and must include terms to the effect that the
632786Ssos * license from Licensee to its licensee is limited to the intellectual
642786Ssos * property embodied in the software Licensee provides to its licensee, and
652786Ssos * not to intellectual property embodied in modifications its licensee may
662786Ssos * make.
672786Ssos *
682786Ssos * 3.3. Redistribution of Executable. Redistribution in executable form of any
692786Ssos * substantial portion of the Covered Code or modification must reproduce the
702786Ssos * above Copyright Notice, and the following Disclaimer and Export Compliance
712786Ssos * provision in the documentation and/or other materials provided with the
722786Ssos * distribution.
732786Ssos *
742786Ssos * 3.4. Intel retains all right, title, and interest in and to the Original
752786Ssos * Intel Code.
762786Ssos *
772786Ssos * 3.5. Neither the name Intel nor any other trademark owned or controlled by
782786Ssos * Intel shall be used in advertising or otherwise to promote the sale, use or
792786Ssos * other dealings in products derived from or relating to the Covered Code
802786Ssos * without prior written authorization from Intel.
815994Ssos *
822786Ssos * 4. Disclaimer and Export Compliance
832786Ssos *
842786Ssos * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
852786Ssos * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
862786Ssos * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
872786Ssos * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
885994Ssos * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
892786Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
902786Ssos * PARTICULAR PURPOSE.
912786Ssos *
922786Ssos * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
932786Ssos * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
942786Ssos * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
952786Ssos * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
962786Ssos * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
972786Ssos * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
982786Ssos * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
992786Ssos * LIMITED REMEDY.
1002786Ssos *
1012786Ssos * 4.3. Licensee shall not export, either directly or indirectly, any of this
1022786Ssos * software or system incorporating such software without first obtaining any
1032786Ssos * required license or other approval from the U. S. Department of Commerce or
1042786Ssos * any other agency or department of the United States Government.  In the
1052786Ssos * event Licensee exports any such software from the United States or
1062786Ssos * re-exports any such software from a foreign destination, Licensee shall
1072786Ssos * ensure that the distribution and export/re-export of the software is in
1085994Ssos * compliance with all laws, regulations, orders, or other restrictions of the
1092786Ssos * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1105994Ssos * any of its subsidiaries will export/re-export any technical data, process,
1115994Ssos * software, or service, directly or indirectly, to any country for which the
1125994Ssos * United States government or any agency thereof requires an export license,
113 * other governmental approval, or letter of assurance, without first obtaining
114 * such license, approval or letter.
115 *
116 *****************************************************************************/
117
118#define __AMSTORE_C__
119
120#include "acpi.h"
121#include "acparser.h"
122#include "acdispat.h"
123#include "acinterp.h"
124#include "amlcode.h"
125#include "acnamesp.h"
126#include "actables.h"
127
128
129#define _COMPONENT          INTERPRETER
130        MODULE_NAME         ("amstore")
131
132
133/*******************************************************************************
134 *
135 * FUNCTION:    AcpiAmlExecStore
136 *
137 * PARAMETERS:  *ValDesc            - Value to be stored
138 *              *DestDesc           - Where to store it 0 Must be (ACPI_HANDLE)
139 *                                    or an ACPI_OPERAND_OBJECT  of type
140 *                                    Reference; if the latter the descriptor
141 *                                    will be either reused or deleted.
142 *
143 * RETURN:      Status
144 *
145 * DESCRIPTION: Store the value described by ValDesc into the location
146 *              described by DestDesc.  Called by various interpreter
147 *              functions to store the result of an operation into
148 *              the destination operand.
149 *
150 ******************************************************************************/
151
152ACPI_STATUS
153AcpiAmlExecStore (
154    ACPI_OPERAND_OBJECT     *ValDesc,
155    ACPI_OPERAND_OBJECT     *DestDesc,
156    ACPI_WALK_STATE         *WalkState)
157{
158    ACPI_STATUS             Status = AE_OK;
159    ACPI_OPERAND_OBJECT     *DeleteDestDesc = NULL;
160    ACPI_OPERAND_OBJECT     *TmpDesc;
161    ACPI_NAMESPACE_NODE     *Node = NULL;
162    UINT8                   Value = 0;
163    UINT32                  Length;
164    UINT32                  i;
165
166
167    FUNCTION_TRACE ("AmlExecStore");
168
169    DEBUG_PRINT (ACPI_INFO, ("entered AcpiAmlExecStore: Val=%p, Dest=%p\n",
170                    ValDesc, DestDesc));
171
172
173    /* Validate parameters */
174
175    if (!ValDesc || !DestDesc)
176    {
177        DEBUG_PRINT (ACPI_ERROR,
178            ("AmlExecStore: Internal error - null pointer\n"));
179        return_ACPI_STATUS (AE_AML_NO_OPERAND);
180    }
181
182    /* Examine the datatype of the DestDesc */
183
184    if (VALID_DESCRIPTOR_TYPE (DestDesc, ACPI_DESC_TYPE_NAMED))
185    {
186        /* Dest is an ACPI_HANDLE, create a new object */
187
188        Node = (ACPI_NAMESPACE_NODE *) DestDesc;
189        DestDesc = AcpiCmCreateInternalObject (INTERNAL_TYPE_REFERENCE);
190        if (!DestDesc)
191        {
192            /* Allocation failure  */
193
194            return_ACPI_STATUS (AE_NO_MEMORY);
195        }
196
197        /* Build a new Reference wrapper around the handle */
198
199        DestDesc->Reference.OpCode = AML_NAME_OP;
200        DestDesc->Reference.Object = Node;
201    }
202
203    else
204    {
205        DEBUG_PRINT (ACPI_INFO,
206            ("AmlExecStore: Dest is object (not handle) - may be deleted!\n"));
207    }
208
209    /* Destination object must be of type Reference */
210
211    if (DestDesc->Common.Type != INTERNAL_TYPE_REFERENCE)
212    {
213        /* Destination is not an Reference */
214
215        DEBUG_PRINT (ACPI_ERROR,
216            ("AmlExecStore: Destination is not an Reference [%p]\n", DestDesc));
217
218        DUMP_STACK_ENTRY (ValDesc);
219        DUMP_STACK_ENTRY (DestDesc);
220        DUMP_OPERANDS (&DestDesc, IMODE_EXECUTE, "AmlExecStore",
221                        2, "target not Reference");
222
223        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
224    }
225
226    /* Examine the Reference opcode */
227
228    switch (DestDesc->Reference.OpCode)
229    {
230
231    case AML_NAME_OP:
232
233        /*
234         *  Storing into a Name
235         */
236        DeleteDestDesc = DestDesc;
237        Status = AcpiAmlStoreObjectToNode (ValDesc, DestDesc->Reference.Object,
238                        WalkState);
239
240        break;  /* Case NameOp */
241
242
243    case AML_INDEX_OP:
244
245        DeleteDestDesc = DestDesc;
246
247        /*
248         * Valid source value and destination reference pointer.
249         *
250         * ACPI Specification 1.0B section 15.2.3.4.2.13:
251         * Destination should point to either a buffer or a package
252         */
253
254        /*
255         * Actually, storing to a package is not so simple.  The source must be
256         * evaluated and converted to the type of the destination and then the
257         * source is copied into the destination - we can't just point to the
258         * source object.
259         */
260        if (DestDesc->Reference.TargetType == ACPI_TYPE_PACKAGE)
261        {
262            /*
263             * The object at *(DestDesc->Reference.Where) is the
264             *  element within the package that is to be modified.
265             */
266            TmpDesc = *(DestDesc->Reference.Where);
267            if (TmpDesc)
268            {
269                /*
270                 * If the Destination element is a package, we will delete
271                 *  that object and construct a new one.
272                 *
273                 * TBD: [Investigate] Should both the src and dest be required
274                 *      to be packages?
275                 *       && (ValDesc->Common.Type == ACPI_TYPE_PACKAGE)
276                 */
277                if (TmpDesc->Common.Type == ACPI_TYPE_PACKAGE)
278                {
279                    /*
280                     * Take away the reference for being part of a package and
281                     * delete
282                     */
283                    AcpiCmRemoveReference (TmpDesc);
284                    AcpiCmRemoveReference (TmpDesc);
285
286                    TmpDesc = NULL;
287                }
288            }
289
290            if (!TmpDesc)
291            {
292                /*
293                 * If the TmpDesc is NULL, that means an uninitialized package
294                 * has been used as a destination, therefore, we must create
295                 * the destination element to match the type of the source
296                 * element NOTE: ValDesc can be of any type.
297                 */
298                TmpDesc = AcpiCmCreateInternalObject (ValDesc->Common.Type);
299                if (!TmpDesc)
300                {
301                    Status = AE_NO_MEMORY;
302                    goto Cleanup;
303                }
304
305                /*
306                 * If the source is a package, copy the source to the new dest
307                 */
308                if (ACPI_TYPE_PACKAGE == TmpDesc->Common.Type)
309                {
310                    Status = AcpiAmlBuildCopyInternalPackageObject (
311                                ValDesc, TmpDesc, WalkState);
312                    if (ACPI_FAILURE (Status))
313                    {
314                        AcpiCmRemoveReference (TmpDesc);
315                        TmpDesc = NULL;
316                        goto Cleanup;
317                    }
318                }
319
320                /*
321                 * Install the new descriptor into the package and add a
322                 * reference to the newly created descriptor for now being
323                 * part of the parent package
324                 */
325
326                *(DestDesc->Reference.Where) = TmpDesc;
327                AcpiCmAddReference (TmpDesc);
328            }
329
330            if (ACPI_TYPE_PACKAGE != TmpDesc->Common.Type)
331            {
332                /*
333                 * The destination element is not a package, so we need to
334                 * convert the contents of the source (ValDesc) and copy into
335                 * the destination (TmpDesc)
336                 */
337                Status = AcpiAmlStoreObjectToObject (ValDesc, TmpDesc,
338                                                        WalkState);
339                if (ACPI_FAILURE (Status))
340                {
341                    /*
342                     * An error occurrered when copying the internal object
343                     * so delete the reference.
344                     */
345                    DEBUG_PRINT (ACPI_ERROR,
346                        ("AmlExecStore/Index: Unable to copy the internal object\n"));
347                    Status = AE_AML_OPERAND_TYPE;
348                }
349            }
350
351            break;
352        }
353
354        /*
355         * Check that the destination is a Buffer Field type
356         */
357        if (DestDesc->Reference.TargetType != ACPI_TYPE_BUFFER_FIELD)
358        {
359            Status = AE_AML_OPERAND_TYPE;
360            break;
361        }
362
363        /*
364         * Storing into a buffer at a location defined by an Index.
365         *
366         * Each 8-bit element of the source object is written to the
367         * 8-bit Buffer Field of the Index destination object.
368         */
369
370        /*
371         * Set the TmpDesc to the destination object and type check.
372         */
373        TmpDesc = DestDesc->Reference.Object;
374
375        if (TmpDesc->Common.Type != ACPI_TYPE_BUFFER)
376        {
377            Status = AE_AML_OPERAND_TYPE;
378            break;
379        }
380
381        /*
382         * The assignment of the individual elements will be slightly
383         * different for each source type.
384         */
385
386        switch (ValDesc->Common.Type)
387        {
388        /*
389         * If the type is Integer, the Length is 4.
390         * This loop to assign each of the elements is somewhat
391         *  backward because of the Big Endian-ness of IA-64
392         */
393        case ACPI_TYPE_NUMBER:
394            Length = 4;
395            for (i = Length; i != 0; i--)
396            {
397                Value = (UINT8)(ValDesc->Number.Value >> (MUL_8 (i - 1)));
398                TmpDesc->Buffer.Pointer[DestDesc->Reference.Offset] = Value;
399            }
400            break;
401
402        /*
403         * If the type is Buffer, the Length is in the structure.
404         * Just loop through the elements and assign each one in turn.
405         */
406        case ACPI_TYPE_BUFFER:
407            Length = ValDesc->Buffer.Length;
408            for (i = 0; i < Length; i++)
409            {
410                Value = *(ValDesc->Buffer.Pointer + i);
411                TmpDesc->Buffer.Pointer[DestDesc->Reference.Offset] = Value;
412            }
413            break;
414
415        /*
416         * If the type is String, the Length is in the structure.
417         * Just loop through the elements and assign each one in turn.
418         */
419        case ACPI_TYPE_STRING:
420            Length = ValDesc->String.Length;
421            for (i = 0; i < Length; i++)
422            {
423                Value = *(ValDesc->String.Pointer + i);
424                TmpDesc->Buffer.Pointer[DestDesc->Reference.Offset] = Value;
425            }
426            break;
427
428        /*
429         * If source is not a valid type so return an error.
430         */
431        default:
432            DEBUG_PRINT (ACPI_ERROR,
433                ("AmlExecStore/Index: Source must be Number/Buffer/String type, not %X\n",
434                ValDesc->Common.Type));
435            Status = AE_AML_OPERAND_TYPE;
436            break;
437        }
438
439        /*
440         * If we had an error, break out of this case statement.
441         */
442        if (ACPI_FAILURE (Status))
443        {
444            break;
445        }
446
447        /*
448         * Set the return pointer
449         */
450        DestDesc = TmpDesc;
451
452        break;
453
454    case AML_ZERO_OP:
455    case AML_ONE_OP:
456    case AML_ONES_OP:
457
458        /*
459         * Storing to a constant is a no-op -- see ACPI Specification
460         * Delete the result descriptor.
461         */
462
463        DeleteDestDesc = DestDesc;
464        break;
465
466
467    case AML_LOCAL_OP:
468
469        Status = AcpiDsMethodDataSetValue (MTH_TYPE_LOCAL,
470                        (DestDesc->Reference.Offset), ValDesc, WalkState);
471        DeleteDestDesc = DestDesc;
472        break;
473
474
475    case AML_ARG_OP:
476
477        Status = AcpiDsMethodDataSetValue (MTH_TYPE_ARG,
478                        (DestDesc->Reference.Offset), ValDesc, WalkState);
479        DeleteDestDesc = DestDesc;
480        break;
481
482
483    case AML_DEBUG_OP:
484
485        /*
486         * Storing to the Debug object causes the value stored to be
487         * displayed and otherwise has no effect -- see ACPI Specification
488         */
489        DEBUG_PRINT (ACPI_INFO, ("**** Write to Debug Object: ****: \n"));
490        if (ValDesc->Common.Type == ACPI_TYPE_STRING)
491        {
492            DEBUG_PRINT (ACPI_INFO, ("%s\n", ValDesc->String.Pointer));
493        }
494        else
495        {
496            DUMP_STACK_ENTRY (ValDesc);
497        }
498
499        DeleteDestDesc = DestDesc;
500        break;
501
502
503    default:
504
505        DEBUG_PRINT (ACPI_ERROR,
506            ("AmlExecStore: Internal error - Unknown Reference subtype %02x\n",
507            DestDesc->Reference.OpCode));
508
509        /* TBD: [Restructure] use object dump routine !! */
510
511        DUMP_BUFFER (DestDesc, sizeof (ACPI_OPERAND_OBJECT));
512
513        DeleteDestDesc = DestDesc;
514        Status = AE_AML_INTERNAL;
515
516    }   /* switch(DestDesc->Reference.OpCode) */
517
518
519Cleanup:
520
521    /* Cleanup and exit*/
522
523    if (DeleteDestDesc)
524    {
525        AcpiCmRemoveReference (DeleteDestDesc);
526    }
527
528    return_ACPI_STATUS (Status);
529}
530
531
532